<!DOCTYPE html><html lang="zh-Hans"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"><meta name="description" content="js高级程序指南第四版--学习记录"><meta name="keywords" content="js"><meta name="author" content="晟松"><meta name="copyright" content="晟松"><title>js高级程序指南第四版--学习记录 | 晟松</title><link rel="shortcut icon" href="/logo.png"><link rel="stylesheet" href="/css/index.css?version=1.9.0"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/font-awesome@latest/css/font-awesome.min.css?version=1.9.0"><meta name="format-detection" content="telephone=no"><meta http-equiv="x-dns-prefetch-control" content="on"><link rel="dns-prefetch" href="https://cdn.jsdelivr.net"><link rel="dns-prefetch" href="https://hm.baidu.com"><script>var _hmt = _hmt || [];
(function() {
  var hm = document.createElement("script");
  hm.src = "https://hm.baidu.com/hm.js?c34d81d53341febe06a155941e2df16d";
  var s = document.getElementsByTagName("script")[0]; 
  s.parentNode.insertBefore(hm, s);
})();</script><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><script>var GLOBAL_CONFIG = { 
  root: '/',
  algolia: undefined,
  localSearch: {"path":"search.xml","languages":{"hits_empty":"找不到您查询的内容:${query}"}},
  copy: {
    success: '复制成功',
    error: '复制错误',
    noSupport: '浏览器不支持'
  },
  hexoVersion: '5.4.0'
} </script><meta name="generator" content="Hexo 5.4.0"></head><body><i class="fa fa-arrow-right" id="toggle-sidebar" aria-hidden="true"></i><div id="sidebar" data-display="true"><div class="toggle-sidebar-info text-center"><span data-toggle="切换文章详情">切换站点概览</span><hr></div><div class="sidebar-toc"><div class="sidebar-toc__title">目录</div><div class="sidebar-toc__progress"><span class="progress-notice">你已经读了</span><span class="progress-num">0</span><span class="progress-percentage">%</span><div class="sidebar-toc__progress-bar"></div></div><div class="sidebar-toc__content"><ol class="toc"><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%B8%A5%E6%A0%BC%E6%A8%A1%E5%BC%8F"><span class="toc-number">1.</span> <span class="toc-text">严格模式</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8F%98%E9%87%8F%E5%A3%B0%E6%98%8E"><span class="toc-number">2.</span> <span class="toc-text">变量声明</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%9F%BA%E6%9C%AC%E7%B1%BB%E5%9E%8B"><span class="toc-number">3.</span> <span class="toc-text">基本类型</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E7%A9%BA%E5%80%BC"><span class="toc-number">3.1.</span> <span class="toc-text">空值</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%95%B0%E5%80%BC%E8%BD%AC%E6%8D%A2"><span class="toc-number">3.2.</span> <span class="toc-text">数值转换</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1"><span class="toc-number">3.3.</span> <span class="toc-text">对象</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E9%80%BB%E8%BE%91%E6%93%8D%E4%BD%9C%E7%AC%A6"><span class="toc-number">3.4.</span> <span class="toc-text">逻辑操作符</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E7%AC%A6%E5%8F%B7%E7%9A%84%E5%88%A4%E6%96%AD"><span class="toc-number">3.5.</span> <span class="toc-text">&#x3D;&#x3D;符号的判断</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%8F%98%E9%87%8F%E3%80%81%E4%BD%9C%E7%94%A8%E5%9F%9F%E4%B8%8E%E5%86%85%E5%AD%98"><span class="toc-number">4.</span> <span class="toc-text">变量、作用域与内存</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%B7%B1%E6%8B%B7%E8%B4%9D%EF%BC%8C%E6%B5%85%E6%8B%B7%E8%B4%9D"><span class="toc-number">4.1.</span> <span class="toc-text">深拷贝，浅拷贝</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%AD%A3%E5%88%99"><span class="toc-number">4.2.</span> <span class="toc-text">正则</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%8E%9F%E5%A7%8B%E5%80%BC%E5%8C%85%E8%A3%85%E7%B1%BB%E5%9E%8B"><span class="toc-number">4.3.</span> <span class="toc-text">原始值包装类型</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%8D%95%E4%BE%8B%E5%86%85%E7%BD%AE%E5%AF%B9%E8%B1%A1"><span class="toc-number">4.4.</span> <span class="toc-text">单例内置对象</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E9%80%89%E6%8B%A9map%E8%BF%98%E6%98%AFobject"><span class="toc-number">4.5.</span> <span class="toc-text">选择map还是object</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#weakmap"><span class="toc-number">4.6.</span> <span class="toc-text">weakmap</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E8%BF%AD%E4%BB%A3%E5%99%A8-%E7%94%9F%E6%88%90%E5%99%A8"><span class="toc-number">5.</span> <span class="toc-text">迭代器 生成器</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E7%94%9F%E6%88%90%E5%99%A8"><span class="toc-number">5.1.</span> <span class="toc-text">生成器</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1%E3%80%81%E7%B1%BB%E3%80%81%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1"><span class="toc-number">6.</span> <span class="toc-text">对象、类、面向对象</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%95%B0%E6%8D%AE%E5%B1%9E%E6%80%A7"><span class="toc-number">6.1.</span> <span class="toc-text">数据属性</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E8%AE%BF%E9%97%AE%E5%99%A8%E5%B1%9E%E6%80%A7"><span class="toc-number">6.2.</span> <span class="toc-text">访问器属性</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%A2%9E%E5%BC%BA%E7%9A%84%E5%AF%B9%E8%B1%A1%E8%AF%AD%E6%B3%95"><span class="toc-number">6.3.</span> <span class="toc-text">增强的对象语法</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%AF%B9%E8%B1%A1%E8%A7%A3%E6%9E%84"><span class="toc-number">6.4.</span> <span class="toc-text">对象解构</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#ES6%E7%9A%84%E7%B1%BB-class-%E7%9A%84%E5%8E%9F%E5%A7%8B%E5%B0%81%E8%A3%85"><span class="toc-number">7.</span> <span class="toc-text">ES6的类 class 的原始封装</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E6%A8%A1%E5%BC%8F"><span class="toc-number">7.1.</span> <span class="toc-text">构造函数模式</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%8E%9F%E5%9E%8B%E6%A8%A1%E5%BC%8F"><span class="toc-number">7.2.</span> <span class="toc-text">原型模式</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E7%BB%A7%E6%89%BF"><span class="toc-number">7.3.</span> <span class="toc-text">继承</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E7%B1%BB"><span class="toc-number">8.</span> <span class="toc-text">类</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#ES6%E7%9A%84%E7%BB%A7%E6%89%BF"><span class="toc-number">8.1.</span> <span class="toc-text">ES6的继承</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BB%A3%E7%90%86%E5%92%8C%E5%8F%8D%E5%B0%84"><span class="toc-number">9.</span> <span class="toc-text">代理和反射</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%8D%95%E8%8E%B7%E5%99%A8"><span class="toc-number">9.1.</span> <span class="toc-text">捕获器</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E4%BB%A3%E7%90%86%E7%9A%84%E9%97%AE%E9%A2%98"><span class="toc-number">9.2.</span> <span class="toc-text">代理的问题</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%85%A8%E9%83%A8%E6%8D%95%E8%8E%B7%E5%99%A8%E5%92%8C%E5%8F%8D%E5%B0%84%E6%96%B9%E6%B3%95"><span class="toc-number">9.3.</span> <span class="toc-text">全部捕获器和反射方法</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%87%BD%E6%95%B0"><span class="toc-number">10.</span> <span class="toc-text">函数</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E7%90%86%E8%A7%A3%E5%8F%82%E6%95%B0"><span class="toc-number">10.1.</span> <span class="toc-text">理解参数</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E9%BB%98%E8%AE%A4%E5%8F%82%E6%95%B0"><span class="toc-number">10.2.</span> <span class="toc-text">默认参数</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#new-target"><span class="toc-number">10.3.</span> <span class="toc-text">new.target</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#arguments-callee"><span class="toc-number">10.4.</span> <span class="toc-text">arguments.callee</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%B0%BE%E8%B0%83%E7%94%A8%E4%BC%98%E5%8C%96"><span class="toc-number">10.5.</span> <span class="toc-text">尾调用优化</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E9%97%AD%E5%8C%85"><span class="toc-number">10.6.</span> <span class="toc-text">闭包</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9C%9F%E7%BA%A6%E4%B8%8E%E5%BC%82%E6%AD%A5%E5%87%BD%E6%95%B0"><span class="toc-number">11.</span> <span class="toc-text">期约与异步函数</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%B3%A8%E6%84%8F"><span class="toc-number">11.1.</span> <span class="toc-text">注意</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#then"><span class="toc-number">11.2.</span> <span class="toc-text">then()</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#catch"><span class="toc-number">11.3.</span> <span class="toc-text">catch()</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#finally"><span class="toc-number">11.4.</span> <span class="toc-text">finally()</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E6%9C%9F%E7%BA%A6%E8%BF%9E%E9%94%81"><span class="toc-number">11.5.</span> <span class="toc-text">期约连锁</span></a><ol class="toc-child"><li class="toc-item toc-level-6"><a class="toc-link" href="#Promise-all-%E5%92%8C-Promise-race"><span class="toc-number">11.5.1.</span> <span class="toc-text">**Promise.all()**和 Promise.race()</span></a></li></ol></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%BC%82%E6%AD%A5%E5%87%BD%E6%95%B0"><span class="toc-number">12.</span> <span class="toc-text">异步函数</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%88%A9%E7%94%A8%E5%BC%82%E6%AD%A5%E5%AE%9E%E7%8E%B0sleep"><span class="toc-number">12.1.</span> <span class="toc-text">利用异步实现sleep</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#BOM"><span class="toc-number">13.</span> <span class="toc-text">BOM</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#DOM"><span class="toc-number">14.</span> <span class="toc-text">DOM</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#Node%E7%B1%BB%E5%9E%8B"><span class="toc-number">14.1.</span> <span class="toc-text">Node类型</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#css%E8%87%AA%E5%AE%9A%E4%B9%89%E5%B1%9E%E6%80%A7"><span class="toc-number">14.2.</span> <span class="toc-text">css自定义属性</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E5%85%83%E7%B4%A0%E5%B0%BA%E5%AF%B8"><span class="toc-number">15.</span> <span class="toc-text">元素尺寸</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%81%8F%E7%A7%BB%E5%B0%BA%E5%AF%B8"><span class="toc-number">15.1.</span> <span class="toc-text">偏移尺寸</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%AE%A2%E6%88%B7%E7%AB%AF%E5%B0%BA%E5%AF%B8"><span class="toc-number">15.2.</span> <span class="toc-text">客户端尺寸</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E4%BA%8B%E4%BB%B6"><span class="toc-number">16.</span> <span class="toc-text">事件</span></a></li><li class="toc-item toc-level-4"><a class="toc-link" href="#canvas"><span class="toc-number">17.</span> <span class="toc-text">canvas</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#%E5%AF%8C%E6%96%87%E6%9C%AC%E7%BC%96%E8%BE%91"><span class="toc-number">17.1.</span> <span class="toc-text">富文本编辑</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E9%87%8D%E8%A6%81%E7%9A%84API"><span class="toc-number">18.</span> <span class="toc-text">重要的API</span></a><ol class="toc-child"><li class="toc-item toc-level-5"><a class="toc-link" href="#file%E7%B1%BB%E5%9E%8B"><span class="toc-number">18.1.</span> <span class="toc-text">file类型</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#Page-Visibility-API"><span class="toc-number">18.2.</span> <span class="toc-text">Page Visibility API</span></a></li><li class="toc-item toc-level-5"><a class="toc-link" href="#%E8%AE%A1%E6%97%B6api"><span class="toc-number">18.3.</span> <span class="toc-text">计时api</span></a></li></ol></li><li class="toc-item toc-level-4"><a class="toc-link" href="#%E6%9C%80%E5%90%8E"><span class="toc-number">19.</span> <span class="toc-text">最后</span></a></li></ol></div></div><div class="author-info hide"><div class="author-info__avatar text-center"><img src="/img/avatar.png"></div><div class="author-info__name text-center">晟松</div><div class="author-info__description text-center">晟松的博客</div><div class="follow-button"><a target="_blank" rel="noopener" href="https://gitee.com/cheng_song">Gitee</a></div><hr><div class="author-info-articles"><a class="author-info-articles__archives article-meta" href="/archives"><span class="pull-left">文章</span><span class="pull-right">52</span></a><a class="author-info-articles__tags article-meta" href="/tags"><span class="pull-left">标签</span><span class="pull-right">45</span></a></div></div></div><div id="content-outer"><div id="top-container" style="background-image: url(/img/blog-bg.jpg)"><div id="page-header"><span class="pull-left"> <a id="site-name" href="/">晟松</a></span><i class="fa fa-bars toggle-menu pull-right" aria-hidden="true"></i><span class="pull-right menus">   <a class="site-page" href="/">Home</a><a class="site-page" href="/archives">Archives</a><a class="site-page" href="/tags">Tags</a><a class="site-page" href="/categories">Categories</a></span><span class="pull-right"><a class="site-page social-icon search"><i class="fa fa-search"></i><span> 搜索</span></a></span></div><div id="post-info"><div id="post-title">js高级程序指南第四版--学习记录</div><div id="post-meta"><time class="post-meta__date"><i class="fa fa-calendar" aria-hidden="true"></i> 2021-01-21</time><div class="post-meta-wordcount"><span>字数总计: </span><span class="word-count">11.3k</span><span class="post-meta__separator">|</span><span>阅读时长: 42 分钟</span></div></div></div></div><div class="layout" id="content-inner"><article id="post"><div class="article-container" id="post-content"><p>这个博客是记录title里面的哪本书里面的一些我觉得我现在还没太明白的一些东西，和一些重点需要记录的</p>
<p><a target="_blank" rel="noopener" href="https://wws.lanzous.com/iH8QXknlvza">js高级程序指南第四版</a><br>密码:c73c</p>
<p>下面就是对这本的书的一些知识点的记录了</p>
<h4 id="严格模式"><a href="#严格模式" class="headerlink" title="严格模式"></a>严格模式</h4><p>在脚本开头加上</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">&quot;use strict&quot;</span><br></pre></td></tr></table></figure>

<p>会对一些不明确的地方进行限制，比如说var的变量提升这些出现奇奇怪怪的结果</p>
<h4 id="变量声明"><a href="#变量声明" class="headerlink" title="变量声明"></a>变量声明</h4><p><strong>let 声明的范围是块作用域，而 var 声明的范围是函数作用域</strong></p>
<p>即var的变量如果声明在函数内，则外部不能访问；而let的作用域是在一个块里面，即在一个大括号里面</p>
<p>而且var声明的变量存在“<strong>提升</strong>”，let就不会</p>
<p>在 let 声明之前的执行瞬间被称为“<strong>暂时性死区</strong>”，在此阶段引用任何后面才声明的变量都会抛出 ReferenceError。</p>
<p><strong>28页</strong>，对for循环里面的var和let进行了解释</p>
<p>JavaScript 引擎会为 for 循环中的 let 声明分别创建独立的变量实例，但const不能声明迭代变量，即不能在for中使用const</p>
<p>但在for-of和for-in中可使用const每次迭代创建一个不变的变量</p>
<h4 id="基本类型"><a href="#基本类型" class="headerlink" title="基本类型"></a>基本类型</h4><p>6种原始类型和一个复杂类型</p>
<p>undefined null Boolean number string symbol   object</p>
<p>在对未初始化的变量调用 typeof 时，返回的结果是”undefined”，但对未声明的变量调用它时，返回的结果还是”undefined”</p>
<p>但实际上还是有差别的</p>
<p><img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20210122104116607.png" alt="image-20210122104116607"></p>
<p>同时还有隐式转换这个有时候会造成很奇怪问题的东西</p>
<p>使用 **!!**可直接对一个值进行Boolean()隐式转换</p>
<h5 id="空值"><a href="#空值" class="headerlink" title="空值"></a>空值</h5><p>下面是一些对空值的判断方式</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//    var a = &quot;&quot;;</span></span><br><span class="line"><span class="comment">//    var a = &quot; &quot;;</span></span><br><span class="line"><span class="comment">//    var a = null;</span></span><br><span class="line"><span class="comment">//    var a = undefined;</span></span><br><span class="line"><span class="comment">//    var a = [];</span></span><br><span class="line"><span class="comment">//    var a = &#123;&#125;;</span></span><br><span class="line"><span class="comment">//    var a = NaN;</span></span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>(a === <span class="literal">undefined</span>) &#123; <span class="comment">// 只能用 === 运算来测试某个值是否是未定义的</span></span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;为undefined&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    </span><br><span class="line">    <span class="keyword">if</span>(a == <span class="literal">null</span>) &#123; <span class="comment">// 等同于 a === undefined || a === null</span></span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;为null&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    </span><br><span class="line">    <span class="comment">// String    </span></span><br><span class="line">    <span class="keyword">if</span>(a == <span class="string">&quot;&quot;</span> || a == <span class="literal">null</span> || a == <span class="literal">undefined</span>)&#123; <span class="comment">// &quot;&quot;,null,undefined</span></span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;为空&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(!a)&#123; <span class="comment">// &quot;&quot;,null,undefined,NaN</span></span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;为空&quot;</span>); </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(!$.trim(a))&#123; <span class="comment">// &quot;&quot;,null,undefined</span></span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;为空&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Array</span></span><br><span class="line">    <span class="keyword">if</span>(a.length == <span class="number">0</span>)&#123; <span class="comment">// &quot;&quot;,[]</span></span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;为空&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">if</span>(!a.length)&#123; <span class="comment">// &quot;&quot;,[]</span></span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;为空&quot;</span>);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// Object &#123;&#125;</span></span><br><span class="line">    <span class="keyword">if</span>($.isEmptyObject(a))&#123; <span class="comment">// 普通对象使用 for...in 判断，有 key 即为 false</span></span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;为空&quot;</span>);</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>



<h5 id="数值转换"><a href="#数值转换" class="headerlink" title="数值转换"></a>数值转换</h5><p>number()     parseInt()     parseFloat()</p>
<p>Symbol.for()对每个字符串键都执行幂等操作。第一次使用某个字符串调用时，它会检查全局运行时注册表，发现不存在对应的符号，于是就会生成一个新符号实例并添加到注册表中。后续使用相同字符串的调用同样会检查注册表，发现存在与该字符串对应的符号，然后就会返回该符号实例</p>
<h5 id="对象"><a href="#对象" class="headerlink" title="对象"></a>对象</h5><p>每个 Object 实例都有如下属性和方法。</p>
<ul>
<li>constructor：用于创建当前对象的函数。在前面的例子中，这个属性的值就是 Object() 函数。</li>
<li>hasOwnProperty(<em>propertyName</em>)：用于判断当前对象实例（不是原型）上是否存在给定的属性。要检查的属性名必须是字符串（如 o.hasOwnProperty(“name”)）或符号。</li>
<li>isPrototypeOf(<em>object</em>)：用于判断当前对象是否为另一个对象的原型。（第 8 章将详细介绍原型。）</li>
<li>propertyIsEnumerable(<em>propertyName</em>)：用于判断给定的属性是否可以使用（本章稍后讨论的）for-in 语句枚举。与 hasOwnProperty()一样，属性名必须是字符串。</li>
<li>toLocaleString()：返回对象的字符串表示，该字符串反映对象所在的本地化执行环境。</li>
<li>toString()：返回对象的字符串表示。</li>
<li>valueOf()：返回对象对应的字符串、数值或布尔值表示。通常与 toString()的返回值相同。</li>
</ul>
<p>valueOf(): 返回最适合该对象类型的原始值；</p>
<p>toString(): 将该对象的原始值以字符串形式返回</p>
<p>在数值运算里，会优先调用valueOf()，如a + b；</p>
<p>在字符串运算里，会优先调用toString()，如alert(c)。</p>
<p><a target="_blank" rel="noopener" href="https://github.com/yangyunhai/FrontendPeople/blob/master/questions/javascipr.md#79--0%E7%AD%89%E4%BA%8E%E4%BB%80%E4%B9%88%E4%B8%BA%E4%BB%80%E4%B9%88">介绍</a></p>
<p>当对象类型需要被转为原始类型时，它会先查找对象的<code>valueOf</code>方法，如果<code>valueOf</code>方法返回原始类型的值，则<code>ToPrimitive</code>的结果就是这个值</p>
<p>如果<code>valueOf</code>不存在或者<code>valueOf</code>方法返回的不是原始类型的值，就会尝试调用对象的<code>toString</code>方法</p>
<h5 id="逻辑操作符"><a href="#逻辑操作符" class="headerlink" title="逻辑操作符"></a>逻辑操作符</h5><p>如 <strong>&amp;&amp;</strong>     <strong>||</strong>    具有短路的特性，即当前面符合的判断的时候可以直接得到最终结果的时候，就不会再对后面进行运算和判断，浪费算力</p>
<p>有时候可根据这个特性简化运算</p>
<p>指数操作符 ****** 即相当于平方</p>
<p>在执行 <strong>+</strong> 的时候如果两个变量不是number，则会直接进行字符串拼接，只有一个number也不行</p>
<p>但执行 <strong>-</strong> 就会将字符串转换为number</p>
<p>不要使用字符串形式的数字来进行比较，如    &lt;     &gt;     其会比较字符的编码，而不是逻辑的字符数字</p>
<h5 id="符号的判断"><a href="#符号的判断" class="headerlink" title="==符号的判断"></a>==符号的判断</h5><img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20210122204107816.png" alt="image-20210122204107816" style="zoom:80%;" />



<p>for-of    value    </p>
<p>for-in    key</p>
<h4 id="变量、作用域与内存"><a href="#变量、作用域与内存" class="headerlink" title="变量、作用域与内存"></a>变量、作用域与内存</h4><p>原始型（六个基本数据类型都是）、引用型</p>
<h5 id="深拷贝，浅拷贝"><a href="#深拷贝，浅拷贝" class="headerlink" title="深拷贝，浅拷贝"></a>深拷贝，浅拷贝</h5><p>可查看之间的博客 js各种知识里面的知识点</p>
<p>js里面<strong>函数的参数</strong>传递是按值传递的（该原始的原始复制，该引用的引用复制）</p>
<h5 id="正则"><a href="#正则" class="headerlink" title="正则"></a>正则</h5><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> reg = <span class="regexp">/cd[da]/g</span></span><br><span class="line"><span class="keyword">let</span> text = <span class="string">&#x27;scda&#x27;</span></span><br><span class="line"><span class="keyword">let</span> match = reg.exec(text)</span><br><span class="line"><span class="keyword">let</span> match1 = text.match(reg)</span><br><span class="line"><span class="built_in">console</span>.log(match,match1)</span><br><span class="line"><span class="comment">// [ &#x27;cda&#x27;, index: 1, input: &#x27;scda&#x27;, groups: undefined ] [ &#x27;cda&#x27; ]</span></span><br></pre></td></tr></table></figure>

<p>通过 <strong>match.index</strong> 这个值是否存在来判断是否这个text里面存在这个reg的对应的字符串和其起始位置</p>
<p>也可通过 <strong>match1</strong> 是否存在判断是否正则匹配</p>
<h5 id="原始值包装类型"><a href="#原始值包装类型" class="headerlink" title="原始值包装类型"></a>原始值包装类型</h5><p>即</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> s1 = <span class="string">&#x27;ds&#x27;</span></span><br><span class="line"><span class="keyword">let</span> s2 = s1.substring(<span class="number">1</span>)</span><br></pre></td></tr></table></figure>

<p>113页有详细解释</p>
<p>这里的s1应该是原始类型，不是对象，那么在这上面就不能直接调用方法，是js后台对s1进行了处理，包装了一个对象，才使得能调用方法，完成之后就会立即销毁</p>
<p>奇怪的知识点</p>
<p>在浏览器控制台里面：</p>
<p><a target="_blank" rel="noopener" href="https://blog.csdn.net/qq_39985511/article/details/94749704">他人文章</a></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="number">12.</span>.toString(<span class="number">2</span>) </span><br><span class="line"><span class="comment">// 或 12 .toString(2) //隔一个空格，使得t前面的那个点 ‘.’ 成为一个token，而不是被当成 12. 变成一个省略的float数字</span></span><br><span class="line"><span class="comment">// 输出 &quot;1100&quot;</span></span><br></pre></td></tr></table></figure>



<h5 id="单例内置对象"><a href="#单例内置对象" class="headerlink" title="单例内置对象"></a>单例内置对象</h5><p>**global    ** <strong>math</strong> </p>
<p>Global 对象有很多属性，其中一些前面已经提到过了。像 undefined、NaN 和 Infinity 等特殊值都是 Global 对象的属性。此外，所有原生引用类型构造函数，比如 Object 和 Function，也都是Global 对象的属性。浏览器将global视为window对象</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">number = <span class="built_in">Math</span>.floor(<span class="built_in">Math</span>.random() * total_number_of_choices + first_possible_value)</span><br><span class="line"><span class="comment">// 取随机数</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">selectFrom</span>(<span class="params">lowerValue, upperValue</span>) </span>&#123; </span><br><span class="line"> <span class="keyword">let</span> choices = upperValue - lowerValue + <span class="number">1</span>; </span><br><span class="line"> <span class="keyword">return</span> <span class="built_in">Math</span>.floor(<span class="built_in">Math</span>.random() * choices + lowerValue); </span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">let</span> num = selectFrom(<span class="number">2</span>,<span class="number">10</span>); </span><br><span class="line"><span class="built_in">console</span>.log(num); <span class="comment">// 2~10 范围内的值，其中包含 2 和 10</span></span><br></pre></td></tr></table></figure>

<h5 id="选择map还是object"><a href="#选择map还是object" class="headerlink" title="选择map还是object"></a>选择map还是object</h5><p>map在给定内存和需要大量插入操作时和需要使用delete时 更具优势</p>
<h5 id="weakmap"><a href="#weakmap" class="headerlink" title="weakmap"></a><strong>weakmap</strong></h5><p>弱映射中的键只能是 Object 或者继承自 Object 的类型（weakset也是如此）</p>
<p>WeakMap 中的weak（弱），描述的是 JavaScript 垃圾回收程序对待“弱映射”中键的方式。</p>
<h4 id="迭代器-生成器"><a href="#迭代器-生成器" class="headerlink" title="迭代器 生成器"></a>迭代器 生成器</h4><p><strong>[Symbol.iterator]</strong>     </p>
<p>接收可迭代对象的原生语言特性包括：</p>
<ul>
<li>for-of 循环</li>
<li>数组解构</li>
<li>扩展操作符（…）</li>
<li>Array.from()</li>
<li>创建集合</li>
<li>创建映射</li>
<li>Promise.all()接收由期约组成的可迭代对象</li>
<li>Promise.race()接收由期约组成的可迭代对象</li>
<li>yield*操作符，在生成器中使用</li>
</ul>
<p>使用 **next() **方法获取每一个值，直到得到 <strong>done: true</strong>为止</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//迭代器并不与可迭代对象某个时刻的快照绑定,会相应变化</span></span><br><span class="line"><span class="keyword">let</span> arr = [<span class="string">&#x27;foo&#x27;</span>, <span class="string">&#x27;baz&#x27;</span>]; </span><br><span class="line"><span class="keyword">let</span> str = <span class="string">&#x27;dsa&#x27;</span>;</span><br><span class="line"><span class="keyword">let</span> iter = arr[<span class="built_in">Symbol</span>.iterator]();</span><br><span class="line"><span class="keyword">let</span> iter1 = str[<span class="built_in">Symbol</span>.iterator]();</span><br><span class="line"><span class="built_in">console</span>.log(iter.next()); <span class="comment">// &#123; done: false, value: &#x27;foo&#x27; &#125; </span></span><br><span class="line"><span class="comment">// 在数组中间插入值</span></span><br><span class="line">arr.splice(<span class="number">1</span>, <span class="number">0</span>, <span class="string">&#x27;bar&#x27;</span>); </span><br><span class="line"><span class="built_in">console</span>.log(iter.next()); <span class="comment">// &#123; done: false, value: &#x27;bar&#x27; &#125; </span></span><br><span class="line"><span class="built_in">console</span>.log(iter.next()); <span class="comment">// &#123; done: false, value: &#x27;baz&#x27; &#125; </span></span><br><span class="line"><span class="built_in">console</span>.log(iter.next()); <span class="comment">// &#123; done: true, value: undefined &#125;</span></span><br></pre></td></tr></table></figure>

<p>return()    方法终止迭代</p>
<h5 id="生成器"><a href="#生成器" class="headerlink" title="生成器"></a>生成器</h5><p>形式是一个函数，函数名称前面加一个星号（*）表示它是一个生成器。只要是可以定义函数的地方，就可以定义生成器</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 生成器函数声明</span></span><br><span class="line"><span class="function"><span class="keyword">function</span>* <span class="title">generatorFn</span>(<span class="params"></span>) </span>&#123;&#125; </span><br><span class="line"><span class="comment">// 生成器函数表达式</span></span><br><span class="line"><span class="keyword">let</span> generatorFn = <span class="function"><span class="keyword">function</span>* (<span class="params"></span>) </span>&#123;&#125;</span><br><span class="line"><span class="comment">// 箭头函数不能定义生成器</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span>* <span class="title">generatorFn</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line"> <span class="keyword">yield</span> <span class="string">&#x27;foo&#x27;</span>; </span><br><span class="line"> <span class="keyword">yield</span> <span class="string">&#x27;bar&#x27;</span>; </span><br><span class="line"> <span class="keyword">return</span> <span class="string">&#x27;baz&#x27;</span>; </span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">let</span> generatorObject = generatorFn();</span><br><span class="line"><span class="comment">// 调用了next()才开始执行</span></span><br><span class="line"><span class="built_in">console</span>.log(generatorObject.next()); <span class="comment">// &#123; done: false, value: &#x27;foo&#x27; &#125; </span></span><br><span class="line"><span class="built_in">console</span>.log(generatorObject.next()); <span class="comment">// &#123; done: false, value: &#x27;bar&#x27; &#125; </span></span><br><span class="line"><span class="built_in">console</span>.log(generatorObject.next()); <span class="comment">// &#123; done: true, value: &#x27;baz&#x27; &#125;</span></span><br></pre></td></tr></table></figure>

<p>　　1、函数生成器特点是函数名前面有一个 *****</p>
<p>　　2、通过调用函数生成一个控制器</p>
<p>　　3、调用next()方法开始执行函数，记住生成器是从next()开始进行执行</p>
<p>　　4、遇到yield函数将暂停，yield不能出现在嵌套的非生成器函数中</p>
<p>　　5、再次调用next()继续执行函数</p>
<p>yield *       迭代一个可迭代对象，从而每次产生一个值</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">yield</span> * [<span class="string">&#x27;312&#x27;</span>,<span class="string">&#x27;dsa&#x27;</span>,<span class="string">&#x27;蒋晟松&#x27;</span>]; </span><br></pre></td></tr></table></figure>



<h4 id="对象、类、面向对象"><a href="#对象、类、面向对象" class="headerlink" title="对象、类、面向对象"></a>对象、类、面向对象</h4><h5 id="数据属性"><a href="#数据属性" class="headerlink" title="数据属性"></a>数据属性</h5><p>数据属性包含一个保存数据值的位置。值会从这个位置读取，也会写入到这个位置</p>
<ul>
<li>[[Configurable]]：表示属性是否可以通过 delete 删除并重新定义，是否可以修改它的特性，以及是否可以把它改为访问器属性。默认情况下，所有直接定义在对象上的属性的这个特性都是 true。一旦变为false就无法变回来</li>
<li> [[Enumerable]]：表示属性是否可以通过 for-in 循环返回。默认情况下，所有直接定义在对象上的属性的这个特性都是 true</li>
<li> [[Writable]]：表示属性的值是否可以被修改。默认情况下，所有直接定义在对象上的属性的这个特性都是 true</li>
<li> [[Value]]：包含属性实际的值。这就是前面提到的那个读取和写入属性值的位置。这个特性的默认值为 undefined。</li>
</ul>
<p>注意两个中括号，是特定进行标识的，表示其为内部特性</p>
<p>可使用 <strong>Object.defineProperty()</strong> 进行修改，还有一个 <strong>Object.defineProperties</strong></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> person = &#123;&#125;; </span><br><span class="line"><span class="built_in">Object</span>.defineProperty(person, <span class="string">&quot;name&quot;</span>, &#123; </span><br><span class="line"> <span class="attr">writable</span>: <span class="literal">false</span>, <span class="comment">// 让其不能被修改</span></span><br><span class="line"> <span class="attr">value</span>: <span class="string">&quot;Nicholas&quot;</span> </span><br><span class="line">&#125;); </span><br><span class="line"><span class="built_in">console</span>.log(person.name); <span class="comment">// &quot;Nicholas&quot; </span></span><br><span class="line">person.name = <span class="string">&quot;Greg&quot;</span>; </span><br><span class="line"><span class="built_in">console</span>.log(person.name); <span class="comment">// &quot;Nicholas&quot;</span></span><br></pre></td></tr></table></figure>

<h5 id="访问器属性"><a href="#访问器属性" class="headerlink" title="访问器属性"></a>访问器属性</h5><p>访问器属性不包含数据值。相反，它们包含一个获取（getter）函数和一个设置（setter）函数，不过这两个函数不是必需的</p>
<ul>
<li><p>[[Configurable]]：表示属性是否可以通过 delete 删除并重新定义，是否可以修改它的特性，以及是否可以把它改为数据属性。默认情况下，所有直接定义在对象上的属性的这个特性都是 true。 </p>
</li>
<li><p> [[Enumerable]]：表示属性是否可以通过 for-in 循环返回。默认情况下，所有直接定义在对象上的属性的这个特性都是 true。 </p>
</li>
<li><p> [[Get]]：获取函数，在读取属性时调用。默认值为 undefined。 </p>
</li>
<li><p> [[Set]]：设置函数，在写入属性时调用。默认值为 undefined。</p>
</li>
</ul>
  <figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> book = &#123; </span><br><span class="line"> <span class="attr">year_</span>: <span class="number">2017</span>, </span><br><span class="line"> <span class="attr">edition</span>: <span class="number">1</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="built_in">Object</span>.defineProperty(book, <span class="string">&quot;year&quot;</span>, &#123; </span><br><span class="line"> <span class="function"><span class="title">get</span>(<span class="params"></span>)</span> &#123; </span><br><span class="line"> 	<span class="keyword">return</span> <span class="built_in">this</span>.year_; </span><br><span class="line"> &#125;, </span><br><span class="line"> <span class="function"><span class="title">set</span>(<span class="params">newValue</span>)</span> &#123; </span><br><span class="line">     <span class="keyword">if</span> (newValue &gt; <span class="number">2017</span>) &#123; </span><br><span class="line">     <span class="built_in">this</span>.year_ = newValue; </span><br><span class="line">     <span class="built_in">this</span>.edition += newValue - <span class="number">2017</span>; </span><br><span class="line">     &#125; </span><br><span class="line"> &#125; </span><br><span class="line">&#125;); </span><br><span class="line">book.year = <span class="number">2018</span>; </span><br><span class="line"><span class="built_in">console</span>.log(book.edition); <span class="comment">// 2</span></span><br></pre></td></tr></table></figure>

<p>使用 Object.getOwnPropertyDescriptor(obj,property)方法可以取得指定属性的属性描述符</p>
<p>同理 <strong>Object.getOwnPropertyDescriptors(obj)</strong></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  <span class="attr">year_</span>: &#123; <span class="attr">value</span>: <span class="number">2018</span>, <span class="attr">writable</span>: <span class="literal">true</span>, <span class="attr">enumerable</span>: <span class="literal">true</span>, <span class="attr">configurable</span>: <span class="literal">true</span> &#125;,</span><br><span class="line">  <span class="attr">edition</span>: &#123; <span class="attr">value</span>: <span class="number">2</span>, <span class="attr">writable</span>: <span class="literal">true</span>, <span class="attr">enumerable</span>: <span class="literal">true</span>, <span class="attr">configurable</span>: <span class="literal">true</span> &#125;,</span><br><span class="line">  <span class="attr">year</span>: &#123;</span><br><span class="line">    <span class="attr">get</span>: [<span class="built_in">Function</span>: get],</span><br><span class="line">    <span class="attr">set</span>: [<span class="built_in">Function</span>: set],</span><br><span class="line">    <span class="attr">enumerable</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="attr">configurable</span>: <span class="literal">false</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<p><strong>object.assign</strong></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 这里主要是直接在对象里面使用set和get也是可以的，只表示针对这个特定属性</span></span><br><span class="line"><span class="keyword">let</span> dest = &#123; </span><br><span class="line">     <span class="keyword">set</span> <span class="title">a</span>(<span class="params">val</span>) &#123; </span><br><span class="line">         <span class="built_in">console</span>.log(<span class="string">`Invoked dest setter with param <span class="subst">$&#123;val&#125;</span>`</span>); </span><br><span class="line">     &#125; </span><br><span class="line">&#125;; </span><br><span class="line"><span class="keyword">let</span> src = &#123; </span><br><span class="line">     <span class="comment">// 注意是属性，不是es6的方法的简写方式</span></span><br><span class="line">     <span class="keyword">get</span> <span class="title">a</span>() &#123; </span><br><span class="line">         <span class="built_in">console</span>.log(<span class="string">&#x27;Invoked src getter&#x27;</span>); </span><br><span class="line">         <span class="keyword">return</span> <span class="string">&#x27;foo&#x27;</span>; </span><br><span class="line">     &#125; </span><br><span class="line">&#125;; </span><br><span class="line"><span class="built_in">Object</span>.assign(dest, src); </span><br><span class="line"><span class="comment">// 调用 src 的获取方法</span></span><br><span class="line"><span class="comment">// 调用 dest 的设置方法并传入参数&quot;foo&quot; </span></span><br><span class="line"><span class="comment">// 因为这里的设置函数不执行赋值操作</span></span><br><span class="line"><span class="comment">// 所以实际上并没有把值转移过来</span></span><br><span class="line"><span class="built_in">console</span>.log(dest); <span class="comment">// &#123; set a(val) &#123;...&#125; &#125;</span></span><br></pre></td></tr></table></figure>



<h5 id="增强的对象语法"><a href="#增强的对象语法" class="headerlink" title="增强的对象语法"></a>增强的对象语法</h5><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> name = <span class="string">&#x27;ds&#x27;</span></span><br><span class="line"><span class="keyword">let</span> key = <span class="string">&#x27;key1&#x27;</span></span><br><span class="line"><span class="keyword">let</span> obj = &#123;</span><br><span class="line">	name,	<span class="comment">// name:name的简写</span></span><br><span class="line">	[key]:<span class="string">&#x27;value&#x27;</span>,	<span class="comment">// 使用中括号使其当成js表达式而不是字符串来求值</span></span><br><span class="line">	<span class="function"><span class="title">sayname</span>(<span class="params"></span>)</span>&#123;	<span class="comment">// 简写方法名</span></span><br><span class="line">		...</span><br><span class="line">	&#125;,</span><br><span class="line">	</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>



<h5 id="对象解构"><a href="#对象解构" class="headerlink" title="对象解构"></a>对象解构</h5><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 使用对象解构</span></span><br><span class="line"><span class="keyword">let</span> person = &#123; </span><br><span class="line"> <span class="attr">name</span>: <span class="string">&#x27;Matt&#x27;</span>, </span><br><span class="line"> <span class="attr">age</span>: <span class="number">27</span> </span><br><span class="line">&#125;; </span><br><span class="line"><span class="keyword">let</span> &#123; <span class="attr">name</span>: personName, <span class="attr">age</span>: personAge &#125; = person; </span><br><span class="line"><span class="built_in">console</span>.log(personName); <span class="comment">// Matt </span></span><br><span class="line"><span class="built_in">console</span>.log(personAge); <span class="comment">// 27</span></span><br><span class="line"><span class="comment">// 可简写和设置默认值</span></span><br><span class="line"><span class="keyword">let</span> &#123;name,age=<span class="number">12</span>&#125; = person</span><br><span class="line"></span><br><span class="line"><span class="comment">// 嵌套解构</span></span><br><span class="line"><span class="keyword">let</span> person = &#123; </span><br><span class="line">     <span class="attr">name</span>: <span class="string">&#x27;Matt&#x27;</span>, </span><br><span class="line">     <span class="attr">age</span>: <span class="number">27</span>, </span><br><span class="line">     <span class="attr">job</span>: &#123; </span><br><span class="line">    	 <span class="attr">title</span>: <span class="string">&#x27;Software engineer&#x27;</span> </span><br><span class="line">     &#125; </span><br><span class="line">&#125;; </span><br><span class="line"><span class="comment">// 声明 title 变量并将 person.job.title 的值赋给它</span></span><br><span class="line"><span class="keyword">let</span> &#123; <span class="attr">job</span>: &#123; title &#125; &#125; = person; </span><br><span class="line"><span class="built_in">console</span>.log(title); <span class="comment">// Software engineer</span></span><br></pre></td></tr></table></figure>

<p>null和undefined不能被解构</p>
<h4 id="ES6的类-class-的原始封装"><a href="#ES6的类-class-的原始封装" class="headerlink" title="ES6的类 class 的原始封装"></a>ES6的类 class 的原始封装</h4><p>下面先记录一些ES6语法封装前的class实现的方式，实际使用还是直接使用ES6的语法即可</p>
<h5 id="构造函数模式"><a href="#构造函数模式" class="headerlink" title="构造函数模式"></a>构造函数模式</h5><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 构造函数模式</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params">name, age, job</span>)</span>&#123; </span><br><span class="line"> <span class="built_in">this</span>.name = name; </span><br><span class="line"> <span class="built_in">this</span>.age = age; </span><br><span class="line"> <span class="built_in">this</span>.job = job; </span><br><span class="line"> <span class="comment">// 主要问题是这里的sayName会重复调用new function创建</span></span><br><span class="line"> <span class="built_in">this</span>.sayName = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line">	 <span class="built_in">console</span>.log(<span class="built_in">this</span>.name); </span><br><span class="line"> &#125;; </span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">let</span> person1 = <span class="keyword">new</span> Person(<span class="string">&quot;Nicholas&quot;</span>, <span class="number">29</span>, <span class="string">&quot;Software Engineer&quot;</span>); </span><br><span class="line"><span class="keyword">let</span> person2 = <span class="keyword">new</span> Person(<span class="string">&quot;Greg&quot;</span>, <span class="number">27</span>, <span class="string">&quot;Doctor&quot;</span>); </span><br><span class="line">person1.sayName(); <span class="comment">// Nicholas </span></span><br><span class="line">person2.sayName(); <span class="comment">// Greg</span></span><br></pre></td></tr></table></figure>

<p>要创建 function Person() 的实例，应使用 new 操作符。以这种方式调用构造函数会执行如下操作。</p>
<p>(1) 在内存中创建一个新对象。</p>
<p>(2) 这个新对象内部的[[Prototype]]特性被赋值为构造函数的 prototype 属性</p>
<p><strong>(3)</strong> 构造函数内部的 this 被赋值为这个新对象（即 this 指向新对象）。</p>
<p>(4) 执行构造函数内部的代码（给新对象添加属性）。</p>
<p>(5) 如果构造函数返回非空对象，则返回该对象；否则，返回刚创建的新对象。</p>
<p>构造函数与普通函数唯一的区别就是调用方式不同。除此之外，构造函数也是函数。并没有把某个函数定义为构造函数的特殊语法。任何函数<strong>只要使用 new 操作符调用就是构造函数</strong>，而不使用 new 操作符调用的函数就是普通函数</p>
<p>这里要记住，在调用一个函数而没有<strong>明确设置 this</strong> 值的情况下（即没有作为对象的方法调用，或者没有使用 call()/apply()调用），this 始终指向 Global 对象（在浏览器中就是 window 对象）</p>
<h5 id="原型模式"><a href="#原型模式" class="headerlink" title="原型模式"></a>原型模式</h5><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 原型模式</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params"></span>) </span>&#123;&#125; </span><br><span class="line">Person.prototype.name = <span class="string">&quot;Nicholas&quot;</span>; </span><br><span class="line">Person.prototype.age = <span class="number">29</span>; </span><br><span class="line">Person.prototype.job = <span class="string">&quot;Software Engineer&quot;</span>; </span><br><span class="line"><span class="comment">// 但这里的sayName是共享的</span></span><br><span class="line">Person.prototype.sayName = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line"> <span class="built_in">console</span>.log(<span class="built_in">this</span>.name); </span><br><span class="line">&#125;; </span><br><span class="line"><span class="comment">// 或</span></span><br><span class="line">    Person.prototype = &#123; </span><br><span class="line"><span class="comment">// 这里需要自己制定constructor的指向，不然会指向object的构造函数，但这也使得[[Enumerable]]变为了true，需要自己改为false</span></span><br><span class="line">         <span class="attr">constructor</span>: Person, </span><br><span class="line">         <span class="attr">name</span>: <span class="string">&quot;Nicholas&quot;</span>, </span><br><span class="line">         <span class="attr">age</span>: <span class="number">29</span>, </span><br><span class="line">         <span class="attr">job</span>: <span class="string">&quot;Software Engineer&quot;</span>, </span><br><span class="line">         <span class="function"><span class="title">sayName</span>(<span class="params"></span>)</span> &#123; </span><br><span class="line">         	<span class="built_in">console</span>.log(<span class="built_in">this</span>.name); </span><br><span class="line">         &#125; </span><br><span class="line">    &#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> person1 = <span class="keyword">new</span> Person(); </span><br><span class="line">person1.sayName(); <span class="comment">// &quot;Nicholas&quot; </span></span><br><span class="line"><span class="keyword">let</span> person2 = <span class="keyword">new</span> Person(); </span><br><span class="line">person2.sayName(); <span class="comment">// &quot;Nicholas&quot; </span></span><br><span class="line"><span class="built_in">console</span>.log(person1.sayName == person2.sayName); <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p>这里可以看下之前记录的一些关于原型的知识记录和博客，里面很简单的介绍了一下</p>
<p>原型模式最大的问题就在于其<strong>引用值共享</strong>的性质</p>
<h5 id="继承"><a href="#继承" class="headerlink" title="继承"></a>继承</h5><p>可使用<strong>原型链</strong>实现继承，但其也有问题，主要问题出现在原型中包含引用值的时候。前面在谈到原型的问题时也提到过，原型中包含的 <strong>引用值</strong>会在所有实例间共享，这也是为什么属性通常会在构造函数中定义而不会定义在原型上的原因。第二个问题是，子类型在实例化时不能给父类型的构造函数传参</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">SuperType</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line"> <span class="built_in">this</span>.colors = [<span class="string">&quot;red&quot;</span>, <span class="string">&quot;blue&quot;</span>, <span class="string">&quot;green&quot;</span>]; </span><br><span class="line">&#125; </span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">SubType</span>(<span class="params"></span>) </span>&#123;&#125; </span><br><span class="line"><span class="comment">// 原型链继承 SuperType </span></span><br><span class="line">SubType.prototype = <span class="keyword">new</span> SuperType(); </span><br><span class="line"><span class="keyword">let</span> instance1 = <span class="keyword">new</span> SubType(); </span><br><span class="line">instance1.colors.push(<span class="string">&quot;black&quot;</span>); </span><br><span class="line"><span class="built_in">console</span>.log(instance1.colors); <span class="comment">// &quot;red,blue,green,black&quot; </span></span><br><span class="line"><span class="keyword">let</span> instance2 = <span class="keyword">new</span> SubType(); </span><br><span class="line"><span class="built_in">console</span>.log(instance2.colors); <span class="comment">// &quot;red,blue,green,black&quot;</span></span><br></pre></td></tr></table></figure>

<p>此外还有 <strong>盗用构造函数（解决了共享的问题，但其中每一个方法都要重新构建，不能重用）、组合继承、原型式继承、寄生式继承、寄生式组合继承</strong></p>
<p>这里就只记录一些解决的问题和本身存在的问题吧，实际要用还是需要使用ES6的<strong>extends</strong>语法</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 组合继承，书上说是目前使用最多的方式</span></span><br><span class="line"><span class="comment">// 使用原型链继承原型上的属性和方法，而通过盗用构造函数继承实例属性。这样既可以把方法定义在原型上以实现重用，又可以让每个实例都有自己的属性。</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">SuperType</span>(<span class="params">name</span>)</span>&#123; </span><br><span class="line"> <span class="built_in">this</span>.name = name; </span><br><span class="line"> <span class="built_in">this</span>.colors = [<span class="string">&quot;red&quot;</span>, <span class="string">&quot;blue&quot;</span>, <span class="string">&quot;green&quot;</span>]; </span><br><span class="line">&#125; </span><br><span class="line">SuperType.prototype.sayName = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line"> <span class="built_in">console</span>.log(<span class="built_in">this</span>.name); </span><br><span class="line">&#125;; </span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">SubType</span>(<span class="params">name, age</span>)</span>&#123; </span><br><span class="line"> <span class="comment">// 继承属性，这里会返回supertype的实例值，所以每一个实例拥有属于自己的属性，不会共享引用值</span></span><br><span class="line"> SuperType.call(<span class="built_in">this</span>, name); </span><br><span class="line"> <span class="built_in">this</span>.age = age; </span><br><span class="line">&#125; </span><br><span class="line"><span class="comment">// 继承方法</span></span><br><span class="line">SubType.prototype = <span class="keyword">new</span> SuperType(); </span><br><span class="line"><span class="comment">// 这里将其constructor改回来</span></span><br><span class="line">SubType.prototype.constructor = SubType;</span><br><span class="line">SubType.prototype.sayAge = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line"> <span class="built_in">console</span>.log(<span class="built_in">this</span>.age); </span><br><span class="line">&#125;; </span><br><span class="line"><span class="keyword">let</span> instance1 = <span class="keyword">new</span> SubType(<span class="string">&quot;Nicholas&quot;</span>, <span class="number">29</span>); </span><br><span class="line"><span class="comment">// 这里改变的只是instance1实例的值，并没有改变supertype的值</span></span><br><span class="line">instance1.colors.push(<span class="string">&quot;black&quot;</span>); </span><br><span class="line"><span class="built_in">console</span>.log(instance1.colors); <span class="comment">// &quot;red,blue,green,black&quot; </span></span><br><span class="line">instance1.sayName(); <span class="comment">// &quot;Nicholas&quot;; </span></span><br><span class="line">instance1.sayAge(); <span class="comment">// 29 </span></span><br><span class="line"><span class="keyword">let</span> instance2 = <span class="keyword">new</span> SubType(<span class="string">&quot;Greg&quot;</span>, <span class="number">27</span>); </span><br><span class="line"><span class="built_in">console</span>.log(instance2.colors); <span class="comment">// &quot;red,blue,green&quot; </span></span><br><span class="line">instance2.sayName(); <span class="comment">// &quot;Greg&quot;; </span></span><br><span class="line">instance2.sayAge(); <span class="comment">// 27</span></span><br></pre></td></tr></table></figure>



<h4 id="类"><a href="#类" class="headerlink" title="类"></a><a target="_blank" rel="noopener" href="https://es6.ruanyifeng.com/#docs/class">类</a></h4><p>终于开始记录类了，其实上面的那些也没有太清楚，只是简单地看了一遍，具体的内核思想还是没有理解</p>
<p>类其实就是一种特殊的函数</p>
<p>函数受函数作用域限制，而类受块作用域限制，默认情况下，类定义中的代码都在严格模式下执行</p>
<p>方法名 constructor 会告诉解释器在使用 new 操作符创建类的新实例时，应该调用这个函数。构造函数的定义不是必需的，不定义构造函数相当于将构造函数定义为空函数</p>
<p>使用 new 调用类的构造函数会执行如下操作。</p>
<p>(1) 在内存中创建一个新对象。</p>
<p>(2) 这个新对象内部的[[Prototype]]指针被赋值为构造函数的 prototype 属性。</p>
<p>(3) 构造函数内部的 this 被赋值为这个新对象（即 this 指向新对象）。</p>
<p>(4) 执行构造函数内部的代码（给新对象添加属性）。</p>
<p>(5) 如果构造函数返回非空对象，则返回该对象；否则，返回刚创建的新对象</p>
<p>类构造函数与构造函数的主要区别是，调用类构造函数<strong>必须使用 new 操作符</strong>。而普通构造函数如果不使用 new 调用，那么就会以全局的 this（通常是 window）作为内部对象。调用类构造函数时如果忘了使用 new 则会抛出错误</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&#123;</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">FunctionDeclaration</span>(<span class="params"></span>) </span>&#123;&#125; </span><br><span class="line"> <span class="class"><span class="keyword">class</span> <span class="title">ClassDeclaration</span> </span>&#123;</span><br><span class="line">     <span class="function"><span class="title">constructor</span>(<span class="params">color</span>)</span> &#123;</span><br><span class="line">         <span class="built_in">this</span>.color = color || <span class="string">&#x27;orange&#x27;</span>;</span><br><span class="line">     &#125;</span><br><span class="line"> &#125; </span><br><span class="line">&#125; </span><br><span class="line"><span class="built_in">console</span>.log(FunctionDeclaration); <span class="comment">// FunctionDeclaration() &#123;&#125; </span></span><br><span class="line"><span class="built_in">console</span>.log(ClassDeclaration); <span class="comment">// ReferenceError: ClassDeclaration is not defined</span></span><br></pre></td></tr></table></figure>



<p>注意：方法与方法之间不需要逗号分隔，加了会报错</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 完整示例</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ClassDeclaration</span> </span>&#123;</span><br><span class="line">    age=<span class="number">231</span>	<span class="comment">// 这种方式也可以将这个属性加到实例上面</span></span><br><span class="line">    <span class="function"><span class="title">constructor</span>(<span class="params">color</span>)</span> &#123;</span><br><span class="line">     <span class="comment">// 添加到 this 的所有内容都会存在于不同的实例上，即为实例属性</span></span><br><span class="line">     <span class="built_in">this</span>.color = color || <span class="string">&#x27;orange&#x27;</span>;</span><br><span class="line">     <span class="built_in">this</span>.name = <span class="string">&#x27;cs&#x27;</span></span><br><span class="line">     <span class="built_in">this</span>.sayName = <span class="function">() =&gt;</span> <span class="built_in">console</span>.log(<span class="built_in">this</span>.name);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 在类块中定义的所有内容都会定义在类的原型上，类方法等同于对象属性，使用实例进行调用</span></span><br><span class="line">    <span class="function"><span class="title">locate</span>(<span class="params"></span>)</span> &#123; </span><br><span class="line">    	<span class="built_in">console</span>.log(<span class="string">&#x27;prototype&#x27;</span>); </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 静态方法定义在类本身上</span></span><br><span class="line">    <span class="keyword">static</span> <span class="function"><span class="title">locate</span>(<span class="params"></span>)</span> &#123; </span><br><span class="line">   	 <span class="built_in">console</span>.log(<span class="string">&#x27;class&#x27;</span>, <span class="built_in">this</span>); </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// 也可使用set和get，这个属性不存在也可以，不会报错,但注意在这个类实例化的时候，当new出来的对象设置实例属性的时候，这个set会被调用</span></span><br><span class="line">    <span class="keyword">set</span> <span class="title">name</span>(<span class="params">newName</span>) &#123; </span><br><span class="line">   	 <span class="built_in">this</span>.name_ = newName; </span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">get</span> <span class="title">name</span>() &#123; </span><br><span class="line">     <span class="keyword">return</span> <span class="built_in">this</span>.name_; </span><br><span class="line">    &#125;</span><br><span class="line">&#125; </span><br><span class="line"><span class="comment">// 但不能在类块中给原型添加原始值或对象作为成员数据</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Person</span> </span>&#123; </span><br><span class="line"> <span class="attr">name</span>: <span class="string">&#x27;Jake&#x27;</span> </span><br><span class="line">&#125; </span><br><span class="line"><span class="comment">// Uncaught SyntaxError: Unexpected token</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 虽然类定义并不显式支持在原型或类上添加成员数据，但在类定义外部，可以手动添加</span></span><br><span class="line">ClassDeclaration.my = <span class="string">&#x27;晟松&#x27;</span></span><br><span class="line">ClassDeclaration.prototype.school = <span class="string">&#x27;hunnu&#x27;</span></span><br><span class="line">ClassDeclaration.locate() <span class="comment">// calss [class ClassDeclaration]</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> p1 = <span class="keyword">new</span> ClassDeclaration(<span class="string">&#x27;red&#x27;</span>)</span><br><span class="line"><span class="built_in">console</span>.log(p1.color) <span class="comment">// red </span></span><br><span class="line"><span class="built_in">console</span>.log(p1.locate()) <span class="comment">// prototype</span></span><br><span class="line"><span class="built_in">console</span>.log(p1.age) <span class="comment">// 231</span></span><br><span class="line">p1.name = <span class="string">&#x27;Jake&#x27;</span>; </span><br><span class="line"><span class="built_in">console</span>.log(p1.name); <span class="comment">// Jake</span></span><br></pre></td></tr></table></figure>

<h5 id="ES6的继承"><a href="#ES6的继承" class="headerlink" title="ES6的继承"></a>ES6的继承</h5><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 不仅可以继承一个类，也可以继承普通的构造函数</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Vehicle</span> </span>&#123;&#125; </span><br><span class="line"><span class="comment">// 继承类</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Bus</span> <span class="keyword">extends</span> <span class="title">Vehicle</span> </span>&#123;&#125; </span><br><span class="line"><span class="keyword">let</span> b = <span class="keyword">new</span> Bus(); </span><br><span class="line"><span class="built_in">console</span>.log(b <span class="keyword">instanceof</span> Bus); <span class="comment">// true </span></span><br><span class="line"><span class="built_in">console</span>.log(b <span class="keyword">instanceof</span> Vehicle); <span class="comment">// true </span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span>(<span class="params"></span>) </span>&#123;&#125; </span><br><span class="line"><span class="comment">// 继承普通构造函数</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Engineer</span> <span class="keyword">extends</span> <span class="title">Person</span> </span>&#123;&#125; </span><br><span class="line"><span class="keyword">let</span> e = <span class="keyword">new</span> Engineer(); </span><br><span class="line"><span class="built_in">console</span>.log(e <span class="keyword">instanceof</span> Engineer); <span class="comment">// true </span></span><br><span class="line"><span class="built_in">console</span>.log(e <span class="keyword">instanceof</span> Person); <span class="comment">// true</span></span><br></pre></td></tr></table></figure>

<p><strong>派生类</strong></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Vehicle</span></span>&#123; </span><br><span class="line">    <span class="function"><span class="title">constructor</span>(<span class="params"></span>)</span> &#123; </span><br><span class="line">     <span class="built_in">this</span>.hasEngine = <span class="literal">true</span>; </span><br><span class="line">    &#125; </span><br><span class="line">    <span class="keyword">static</span> <span class="function"><span class="title">identify</span>(<span class="params"></span>)</span> &#123; </span><br><span class="line">     <span class="built_in">console</span>.log(<span class="string">&#x27;vehicle&#x27;</span>); </span><br><span class="line">    &#125;</span><br><span class="line">&#125; </span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Bus</span> <span class="keyword">extends</span> <span class="title">Vehicle</span> </span>&#123; </span><br><span class="line"> <span class="function"><span class="title">constructor</span>(<span class="params"></span>)</span> &#123; </span><br><span class="line">     <span class="comment">// super只能在派生类中使用，而且仅限于类构造函数、实例方法和静态方法内部。在类构造函数中使用 super 可以调用父类构造函数</span></span><br><span class="line">     <span class="comment">// 不要在调用 super()之前引用 this，否则会抛出 ReferenceError </span></span><br><span class="line">     <span class="built_in">super</span>(); <span class="comment">// 相当于 super.constructor() </span></span><br><span class="line">     <span class="built_in">console</span>.log(<span class="built_in">this</span> <span class="keyword">instanceof</span> Vehicle); <span class="comment">// true </span></span><br><span class="line">     <span class="built_in">console</span>.log(<span class="built_in">this</span>); <span class="comment">// Bus &#123; hasEngine: true &#125; </span></span><br><span class="line"> 	&#125;</span><br><span class="line">    <span class="comment">// 在静态方法中可以通过 super 调用继承的类上定义的静态方法</span></span><br><span class="line">    <span class="keyword">static</span> <span class="function"><span class="title">identify</span>(<span class="params"></span>)</span> &#123; </span><br><span class="line">     <span class="built_in">super</span>.identify(); </span><br><span class="line">    &#125;</span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">new</span> Bus();</span><br></pre></td></tr></table></figure>

<p>注意使用super的问题：</p>
<ul>
<li>super 只能在派生类构造函数和静态方法中使用。</li>
<li>不能单独引用 super 关键字，要么用它调用构造函数，要么用它引用静态方法</li>
<li>调用 super()会调用父类构造函数，并将返回的实例赋值给 this。</li>
<li>super()的行为如同调用构造函数，如果需要给父类构造函数传参，则需要手动传入</li>
<li>如果没有定义类构造函数，在实例化派生类时会调用 super()，而且会传入所有传给派生类的参数</li>
<li>在类构造函数中，不能在调用 super()之前引用 this。</li>
<li>如果在派生类中<strong>显式</strong>定义了构造函数，则要么必须在其中调用 super()，要么必须在其中返回一个对象。</li>
</ul>
<p>此外还有Object.assign()方法是为了混入对象的属性，类混入来嵌套混入类</p>
<h4 id="代理和反射"><a href="#代理和反射" class="headerlink" title="代理和反射"></a>代理和反射</h4><p>这里主要是因为vue3的响应式就是通过proxy和reflect来实现的，所以记录一下</p>
<p>默认情况下，在代理对象上执行的所有操作都会无障碍地传播到目标对象</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> target = &#123; </span><br><span class="line"> <span class="attr">id</span>: <span class="string">&#x27;target&#x27;</span> </span><br><span class="line">&#125;; </span><br><span class="line"><span class="comment">// 注意这里是一个对象，不是一个函数</span></span><br><span class="line"><span class="keyword">const</span> handler = &#123;</span><br><span class="line">    <span class="comment">// 捕获器在处理程序对象中以方法名为键</span></span><br><span class="line">    <span class="comment">// 目标对象、要查询的属性和代理对象三个参数，可使用reflect简化</span></span><br><span class="line"> 	<span class="function"><span class="title">get</span>(<span class="params">trapTarget, property, receiver</span>)</span> &#123; </span><br><span class="line"> 		<span class="keyword">return</span> trapTarget[property]; </span><br><span class="line"> 	&#125;</span><br><span class="line">    或</span><br><span class="line">    <span class="function"><span class="title">get</span>(<span class="params"></span>)</span> &#123; </span><br><span class="line"> 		<span class="keyword">return</span> <span class="built_in">Reflect</span>.get(...arguments); </span><br><span class="line"> 	&#125;</span><br><span class="line">	或</span><br><span class="line">	<span class="attr">get</span>: <span class="built_in">Reflect</span>.get</span><br><span class="line">	或</span><br><span class="line">    <span class="function"><span class="title">get</span>(<span class="params">trapTarget, property, receiver</span>)</span> &#123; </span><br><span class="line">         <span class="comment">// 在这里对需要返回的值进行修饰</span></span><br><span class="line">         <span class="keyword">let</span> decoration = <span class="string">&#x27;&#x27;</span>; </span><br><span class="line">         <span class="keyword">if</span> (property === <span class="string">&#x27;foo&#x27;</span>) &#123; </span><br><span class="line">            decoration = <span class="string">&#x27;!!!&#x27;</span>; </span><br><span class="line">         &#125; </span><br><span class="line">         <span class="keyword">return</span> <span class="built_in">Reflect</span>.get(...arguments) + decoration; </span><br><span class="line">     &#125;</span><br><span class="line">&#125;; </span><br><span class="line"><span class="keyword">const</span> proxy = <span class="keyword">new</span> <span class="built_in">Proxy</span>(target, handler);</span><br><span class="line"><span class="comment">// proxy没有prototype属性</span></span><br><span class="line"><span class="comment">// 严格相等可以用来区分代理和目标</span></span><br><span class="line"><span class="built_in">console</span>.log(target === proxy); <span class="comment">// false</span></span><br></pre></td></tr></table></figure>

<h5 id="捕获器"><a href="#捕获器" class="headerlink" title="捕获器"></a>捕获器</h5><p>使用代理的主要目的是可以定义捕获器（trap）。捕获器就是在处理程序对象中定义的“基本操作的拦截器”，就是上面的get</p>
<p>同时还有捕获器不变式、可撤销代理、代理另一个代理</p>
<h5 id="代理的问题"><a href="#代理的问题" class="headerlink" title="代理的问题"></a>代理的问题</h5><p>代理中的this会丢失</p>
<h5 id="全部捕获器和反射方法"><a href="#全部捕获器和反射方法" class="headerlink" title="全部捕获器和反射方法"></a>全部捕获器和反射方法</h5><p>具体的使用方法还是需要时再查吧，这里就记一下</p>
<img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20210125104314863.png" alt="image-20210125104314863" style="zoom: 80%;" />



<h4 id="函数"><a href="#函数" class="headerlink" title="函数"></a>函数</h4><p>函数声明（会出现<strong>声明提升</strong>的现象）、函数表达式、箭头函数、函数构造函数这几种方式创建函数</p>
<p>注意箭头函数没有arguments，<strong>其this也跟其他函数不一样，是其创建时的this，而不是调用时的this</strong></p>
<p>使用不带括号的函数名会访问函数指针，而不会执行函数，同时也有立即函数这一说</p>
<p>ES6的所有函数对象都会暴露一个只读的 name 属性，表示一个函数标识符</p>
<p>js中没有函数重载，函数名可被当作指针来进行理解</p>
<h5 id="理解参数"><a href="#理解参数" class="headerlink" title="理解参数"></a>理解参数</h5><p>ECMAScript 函数的参数在内部表现为一个数组arguments，是一个类数组，但不建议使用，建议使用扩展（收集）参数</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 收集参数的前面如果还有命名参数，则只会收集其余的参数；如果没有则会得到空数组。因为收集参数的结果可变，所以只能把它作为最后一个参数</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getSum</span>(<span class="params">...values</span>) </span>&#123; </span><br><span class="line"> <span class="comment">// 顺序累加 values 中的所有值</span></span><br><span class="line"> <span class="comment">// 初始值的总和为 0 </span></span><br><span class="line"> <span class="keyword">return</span> values.reduce(<span class="function">(<span class="params">x, y</span>) =&gt;</span> x + y, <span class="number">0</span>); </span><br><span class="line">&#125; </span><br><span class="line"><span class="built_in">console</span>.log(getSum(<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>)); <span class="comment">// 6</span></span><br></pre></td></tr></table></figure>

<p>arguments 对象的另一个有意思的地方就是，它的值始终会与对应的命名参数同步</p>
<h5 id="默认参数"><a href="#默认参数" class="headerlink" title="默认参数"></a>默认参数</h5><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 默认参数按照顺序被创建，后面的参数可引用前面的参数，且遵循暂时性时区规则，即前面定义的参数不能引用后面定义的</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">makeKing</span>(<span class="params">name = <span class="string">&#x27;Henry&#x27;</span>,ts = name</span>) </span>&#123; </span><br><span class="line"> <span class="keyword">return</span> <span class="string">`King <span class="subst">$&#123;name&#125;</span> VIII`</span>; </span><br><span class="line">&#125; </span><br><span class="line"><span class="built_in">console</span>.log(makeKing(<span class="string">&#x27;Louis&#x27;</span>)); <span class="comment">// &#x27;King Louis VIII&#x27; </span></span><br><span class="line"><span class="built_in">console</span>.log(makeKing()); <span class="comment">// &#x27;King Henry VIII&#x27;</span></span><br></pre></td></tr></table></figure>

<p>在使用默认参数时，arguments 对象的值不反映参数的默认值，只反映传给函数的参数</p>
<h5 id="new-target"><a href="#new-target" class="headerlink" title="new.target"></a>new.target</h5><p>检测函数是否使用 new 关键字调用的 new.target 属性</p>
<h5 id="arguments-callee"><a href="#arguments-callee" class="headerlink" title="arguments.callee"></a>arguments.callee</h5><p>就是一个指向正在执行的函数的指针，可用于递归时代替函数名</p>
<h5 id="尾调用优化"><a href="#尾调用优化" class="headerlink" title="尾调用优化"></a>尾调用优化</h5><p>即外部函数的返回值是<strong>一个</strong>内部函数的返回值。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">outerFunction</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line"> <span class="keyword">return</span> innerFunction(); <span class="comment">// 尾调用</span></span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 无优化</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fib</span>(<span class="params">n</span>) </span>&#123; </span><br><span class="line"> <span class="keyword">if</span> (n &lt; <span class="number">2</span>) &#123; </span><br><span class="line"> <span class="keyword">return</span> n; </span><br><span class="line"> &#125; </span><br><span class="line"> <span class="keyword">return</span> fib(n - <span class="number">1</span>) + fib(n - <span class="number">2</span>); </span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// 优化</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fibImpl</span>(<span class="params">a, b, n</span>) </span>&#123; </span><br><span class="line"> <span class="keyword">if</span> (n === <span class="number">0</span>) &#123; </span><br><span class="line"> <span class="keyword">return</span> a; </span><br><span class="line"> &#125; </span><br><span class="line"> <span class="keyword">return</span> fibImpl(b, a + b, n - <span class="number">1</span>); </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h5 id="闭包"><a href="#闭包" class="headerlink" title="闭包"></a><a target="_blank" rel="noopener" href="https://zh.javascript.info/closure">闭包</a></h5><p>指的是那些引用了另一个函数作用域中变量的函数，通常是在嵌套函数中实现</p>
<p>在调用一个函数时，会为这个函数调用创建一个执行上下文，并创建一个作用域链。然后用 arguments和其他命名参数来初始化这个函数的活动对象。外部函数的活动对象是内部函数作用域链上的第二个对象。这个作用域链一直向外串起了所有包含函数的活动对象，直到全局执行上下文才终止。</p>
<p>闭包在被函数返回之后，其作用域会一直保存在内存中，直到闭包被销毁。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 一种特殊的情况</span></span><br><span class="line"><span class="built_in">window</span>.identity = <span class="string">&#x27;The Window&#x27;</span>;</span><br><span class="line"><span class="keyword">let</span> object = &#123; </span><br><span class="line"> <span class="attr">identity</span>: <span class="string">&#x27;My Object&#x27;</span>, </span><br><span class="line"> <span class="function"><span class="title">getIdentityFunc</span>(<span class="params"></span>)</span> &#123; </span><br><span class="line"> 	<span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line"> 		<span class="keyword">return</span> <span class="built_in">this</span>.identity; </span><br><span class="line"> 	&#125;; </span><br><span class="line"> &#125; </span><br><span class="line">&#125;; </span><br><span class="line"><span class="built_in">console</span>.log(object.getIdentityFunc()()); <span class="comment">// &#x27;The Window&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> object1 = &#123; </span><br><span class="line"> <span class="attr">identity</span>: <span class="string">&#x27;My Object&#x27;</span>, </span><br><span class="line"> <span class="function"><span class="title">getIdentityFunc</span>(<span class="params"></span>)</span> &#123; </span><br><span class="line">     <span class="keyword">let</span> that = <span class="built_in">this</span>; </span><br><span class="line">     <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line">         <span class="keyword">return</span> that.identity; </span><br><span class="line">     &#125;; </span><br><span class="line"> &#125; </span><br><span class="line">&#125;; </span><br><span class="line"><span class="built_in">console</span>.log(object1.getIdentityFunc()()); <span class="comment">// &#x27;My Object&#x27;</span></span><br></pre></td></tr></table></figure>



<h4 id="期约与异步函数"><a href="#期约与异步函数" class="headerlink" title="期约与异步函数"></a>期约与异步函数</h4><p>这一部分的promise可以简单的看一下我之前写的一个关于promise的简单介绍和一个关于异步线程的知识，这里就记一些高级一点的知识点</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 一个简单的示例</span></span><br><span class="line"><span class="keyword">let</span> p2 = <span class="keyword">async</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> k = <span class="keyword">await</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">            <span class="built_in">console</span>.log(<span class="string">&quot;异步&quot;</span>);</span><br><span class="line">            resolve(<span class="string">&quot;返回异步值&quot;</span>);</span><br><span class="line">        &#125;, <span class="number">900</span>);</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;promise&quot;</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&quot;k: &quot;</span>, k);</span><br><span class="line">&#125;;</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;晟松&quot;</span>);</span><br><span class="line">p2();</span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&quot;hunnu&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 结果</span></span><br><span class="line">晟松</span><br><span class="line">promise</span><br><span class="line">hunnu</span><br><span class="line">异步</span><br><span class="line"><span class="attr">k</span>:  返回异步值</span><br></pre></td></tr></table></figure>

<h5 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h5><p>Promise.resolve()如果传入的参数本身是一个期约，那它的行为就类似于一个空包装。因此，Promise.resolve()可以说是一个幂等方法</p>
<p>Promise.reject()并没有照搬 Promise.resolve()的幂等逻辑。如果给它传一个期约对象，则这个期约会成为它返回的拒绝期约的理由</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">try</span> &#123; </span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">&#x27;foo&#x27;</span>); </span><br><span class="line">&#125; <span class="keyword">catch</span>(e) &#123; </span><br><span class="line"> <span class="built_in">console</span>.log(e); <span class="comment">// Error: foo </span></span><br><span class="line">&#125; </span><br><span class="line"><span class="keyword">try</span> &#123; </span><br><span class="line"> <span class="built_in">Promise</span>.reject(<span class="keyword">new</span> <span class="built_in">Error</span>(<span class="string">&#x27;bar&#x27;</span>)); </span><br><span class="line">&#125; <span class="keyword">catch</span>(e) &#123; </span><br><span class="line"> <span class="built_in">console</span>.log(e); </span><br><span class="line">&#125; </span><br><span class="line"><span class="comment">// Uncaught (in promise) Error: bar</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 正确</span></span><br><span class="line"><span class="built_in">Promise</span>.reject(<span class="built_in">Error</span>(<span class="string">&#x27;foo&#x27;</span>)).catch(<span class="function">(<span class="params">e</span>) =&gt;</span> &#123;&#125;);</span><br></pre></td></tr></table></figure>

<p>拒绝期约的错误并没有抛到执行同步代码的线程里，而是通过浏览器异步消息队列来处理的。因此，try/catch 块并不能捕获该错误。代码一旦开始以异步模式执行，则唯一与之交互的方式就是使用异步结构—-更具体地说，就是期约的方法</p>
<h5 id="then"><a href="#then" class="headerlink" title="then()"></a>then()</h5><p>两个参数：onResolved 处理程序和 onRejected 处理程序。这两个参数都是可选的，如果提供的话，则会在期约分别进入“兑现”和“拒绝”状态时执行。</p>
<p>同时执行之后返回一个新的promise实例，这个新期约实例基于 onResovled 处理程序的返回值构建，如果没有提供这个处理程序，则 Promise.resolve()就会包装上一个期约解决之后的值。如果没有显式的返回语句，则 Promise.resolve()会包装默认的返回值 undefined。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> p1 = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;p1异步开始&quot;</span>);</span><br><span class="line">        resolve(<span class="string">&quot;返回异步值p1&quot;</span>);</span><br><span class="line">    &#125;, <span class="number">200</span>);</span><br><span class="line">    <span class="comment">// console.log(&quot;promise&quot;);</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> k1 = p1.then(</span><br><span class="line">    <span class="function">(<span class="params">res</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;res&quot;</span>, res);</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="function">(<span class="params">err</span>) =&gt;</span> &#123;</span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&quot;err reject: &quot;</span>, err);</span><br><span class="line">    &#125;</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 结果</span></span><br><span class="line">p1异步开始</span><br><span class="line">res 返回异步值p1</span><br></pre></td></tr></table></figure>

<h5 id="catch"><a href="#catch" class="headerlink" title="catch()"></a>catch()</h5><p>用于给期约添加拒绝处理程序。事实上，这个方法就是一个语法糖，调用它就相当于调用 Promise.prototype. then(null, onRejected)</p>
<h5 id="finally"><a href="#finally" class="headerlink" title="finally()"></a>finally()</h5><p>在期约转换为解决或拒绝状态时都会执行。这个方法可以避免 onResolved 和 onRejected 处理程序中出现冗余代码。但 onFinally 处理程序没有办法知道期约的状态是解决还是拒绝，所以这个方法<strong>主要用于添加清理代码</strong>。并返回一个新的期约实例，在大多数情况下它将表现为父期约的传递。对于已解决状态和被拒绝状态都是如此</p>
<h5 id="期约连锁"><a href="#期约连锁" class="headerlink" title="期约连锁"></a>期约连锁</h5><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> p = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> &#123; </span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">&#x27;initial promise rejects&#x27;</span>); </span><br><span class="line"> reject(); </span><br><span class="line">&#125;); </span><br><span class="line">p.catch(<span class="function">() =&gt;</span> <span class="built_in">console</span>.log(<span class="string">&#x27;reject handler&#x27;</span>)) </span><br><span class="line"> .then(<span class="function">() =&gt;</span> <span class="built_in">console</span>.log(<span class="string">&#x27;resolve handler&#x27;</span>)) </span><br><span class="line"> .finally(<span class="function">() =&gt;</span> <span class="built_in">console</span>.log(<span class="string">&#x27;finally handler&#x27;</span>));</span><br><span class="line"></span><br><span class="line"><span class="comment">// initial promise rejects </span></span><br><span class="line"><span class="comment">// reject handler </span></span><br><span class="line"><span class="comment">// resolve handler </span></span><br><span class="line"><span class="comment">// finally handler</span></span><br></pre></td></tr></table></figure>

<h6 id="Promise-all-和-Promise-race"><a href="#Promise-all-和-Promise-race" class="headerlink" title="**Promise.all()**和 Promise.race()"></a>**Promise.all()**和 <strong>Promise.race()</strong></h6><p>这两个可以将两个或多个期约实例组合成一个期约，传递的参数形式是一个数组</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 如果至少有一个包含的期约待定，则合成的期约也会待定。如果有一个包含的期约拒绝，则合成的期约也会拒绝</span></span><br><span class="line"><span class="keyword">let</span> p = <span class="built_in">Promise</span>.all([ </span><br><span class="line"> <span class="built_in">Promise</span>.resolve(), </span><br><span class="line"> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> <span class="built_in">setTimeout</span>(resolve, <span class="number">1000</span>)) </span><br><span class="line">]); </span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="built_in">console</span>.log, <span class="number">0</span>, p); <span class="comment">// Promise &lt;pending&gt; </span></span><br><span class="line">p.then(<span class="function">() =&gt;</span> <span class="built_in">setTimeout</span>(<span class="built_in">console</span>.log, <span class="number">0</span>, <span class="string">&#x27;all() resolved!&#x27;</span>)); </span><br><span class="line"><span class="comment">// all() resolved!（大约 1 秒后）</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 如果所有期约都成功解决，则合成期约的解决值就是所有包含期约解决值的数组，按照迭代器顺序 </span></span><br><span class="line"><span class="keyword">let</span> p = <span class="built_in">Promise</span>.all([ </span><br><span class="line"> <span class="built_in">Promise</span>.resolve(<span class="number">3</span>), </span><br><span class="line"> <span class="built_in">Promise</span>.resolve(), </span><br><span class="line"> <span class="built_in">Promise</span>.resolve(<span class="number">4</span>) </span><br><span class="line">]); </span><br><span class="line">p.then(<span class="function">(<span class="params">values</span>) =&gt;</span> <span class="built_in">setTimeout</span>(<span class="built_in">console</span>.log, <span class="number">0</span>, values)); <span class="comment">// [3, undefined, 4]</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// Promise.race()不会对解决或拒绝的期约区别对待。无论是解决还是拒绝，只要是第一个落定的期约，Promise.race()就会包装其解决值或拒绝理由并返回新期约</span></span><br><span class="line"><span class="comment">// 解决先发生，超时后的拒绝被忽略</span></span><br><span class="line"><span class="keyword">let</span> p1 = <span class="built_in">Promise</span>.race([ </span><br><span class="line"> <span class="built_in">Promise</span>.resolve(<span class="number">3</span>), </span><br><span class="line"> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> <span class="built_in">setTimeout</span>(reject, <span class="number">1000</span>)) </span><br><span class="line">]); </span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="built_in">console</span>.log, <span class="number">0</span>, p1); <span class="comment">// Promise &lt;resolved&gt;: 3 </span></span><br><span class="line"><span class="comment">// 拒绝先发生，超时后的解决被忽略</span></span><br><span class="line"><span class="keyword">let</span> p2 = <span class="built_in">Promise</span>.race([ </span><br><span class="line"> <span class="built_in">Promise</span>.reject(<span class="number">4</span>), </span><br><span class="line"> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> <span class="built_in">setTimeout</span>(resolve, <span class="number">1000</span>)) </span><br><span class="line">]); </span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="built_in">console</span>.log, <span class="number">0</span>, p2); <span class="comment">// Promise &lt;rejected&gt;: 4 </span></span><br><span class="line"><span class="comment">// 迭代顺序决定了落定顺序</span></span><br><span class="line"><span class="keyword">let</span> p3 = <span class="built_in">Promise</span>.race([ </span><br><span class="line"> <span class="built_in">Promise</span>.resolve(<span class="number">5</span>), </span><br><span class="line"> <span class="built_in">Promise</span>.resolve(<span class="number">6</span>), </span><br><span class="line"> <span class="built_in">Promise</span>.resolve(<span class="number">7</span>) </span><br><span class="line">]); </span><br><span class="line"><span class="built_in">setTimeout</span>(<span class="built_in">console</span>.log, <span class="number">0</span>, p3); <span class="comment">// Promise &lt;resolved&gt;: 5</span></span><br></pre></td></tr></table></figure>



<h4 id="异步函数"><a href="#异步函数" class="headerlink" title="异步函数"></a>异步函数</h4><p>异步函数，也称为“async/await”（语法关键字），让以同步方式写的代码异步执行</p>
<p>注意await关键字必须在异步函数中使用</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 原来的异步代码</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">handler</span>(<span class="params">x</span>) </span>&#123; <span class="built_in">console</span>.log(x); &#125; </span><br><span class="line"><span class="keyword">let</span> p = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> <span class="built_in">setTimeout</span>(resolve, <span class="number">1000</span>, <span class="number">3</span>)); </span><br><span class="line">p.then(handler); <span class="comment">// 3</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 现在的异步代码</span></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> p = <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =&gt;</span> <span class="built_in">setTimeout</span>(resolve, <span class="number">1000</span>, <span class="number">3</span>));</span><br><span class="line">    <span class="comment">// await 关键字会暂停执行异步函数后面的代码，让出 JavaScript 运行时的执行线程。这个行为与生成器函数中的 yield 关键字是一样的。</span></span><br><span class="line"> 	<span class="built_in">console</span>.log(<span class="keyword">await</span> p);</span><br><span class="line">&#125; </span><br><span class="line"></span><br><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line"> <span class="built_in">console</span>.log(<span class="number">2</span>); </span><br><span class="line"> <span class="keyword">await</span> <span class="literal">null</span>; </span><br><span class="line"> <span class="built_in">console</span>.log(<span class="number">4</span>); </span><br><span class="line">&#125; </span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">1</span>); </span><br><span class="line">foo(); </span><br><span class="line"><span class="built_in">console</span>.log(<span class="number">3</span>); </span><br><span class="line"><span class="comment">// 1 </span></span><br><span class="line"><span class="comment">// 2 </span></span><br><span class="line"><span class="comment">// 3 </span></span><br><span class="line"><span class="comment">// 4</span></span><br></pre></td></tr></table></figure>

<h5 id="利用异步实现sleep"><a href="#利用异步实现sleep" class="headerlink" title="利用异步实现sleep"></a>利用异步实现sleep</h5><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">async</span> <span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123; </span><br><span class="line"> <span class="keyword">const</span> t0 = <span class="built_in">Date</span>.now();</span><br><span class="line"> <span class="comment">// 加入非阻塞的暂停</span></span><br><span class="line"> <span class="keyword">await</span> sleep(<span class="number">1500</span>); <span class="comment">// 暂停约 1500 毫秒</span></span><br><span class="line"> <span class="built_in">console</span>.log(<span class="built_in">Date</span>.now() - t0); </span><br><span class="line">&#125; </span><br><span class="line">foo(); </span><br><span class="line"><span class="comment">// 1502</span></span><br></pre></td></tr></table></figure>



<h4 id="BOM"><a href="#BOM" class="headerlink" title="BOM"></a>BOM</h4><p>一些关于浏览器的属性，就记一些比较重点的点，具体的使用需要时再查</p>
<p>screenTop（）    scrollTo()     scrollBy（）</p>
<p>还有一些关于浏览器和其中的元素的位置之类的api，需要时可查</p>
<p><strong>Location对象</strong></p>
<p>它既是 window 的属性，也是 document 的属性</p>
<p><img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20210126110959762.png" alt="image-20210126110959762"></p>
<p><strong>history对象</strong></p>
<p>主要是 **go()**方法</p>
<p>还有一个关于浏览器的能力检测，检测是什么浏览器、软硬件这些，需要的时候查一下就好</p>
<h4 id="DOM"><a href="#DOM" class="headerlink" title="DOM"></a>DOM</h4><p>跟前面的BOM差不多，记点比较重要的</p>
<h5 id="Node类型"><a href="#Node类型" class="headerlink" title="Node类型"></a>Node类型</h5><p>document中的每个节点都有nodeType类型，节点直接具有父子关系，如childNodes</p>
<p>还有一些其他的</p>
<p>appendChild()、removeChild()和 replaceChild()方法</p>
<p>定位元素：getElementById()和 getElementsByTagName()还有className这些</p>
<p><strong>MutationObserver</strong></p>
<p>观察一个node的属性变化、文本变化、子节点变化等</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> observer = <span class="keyword">new</span> MutationObserver(<span class="function">() =&gt;</span> <span class="built_in">console</span>.log(<span class="string">&#x27;DOM was mutated!&#x27;</span>)</span><br><span class="line">observer.observe(<span class="built_in">document</span>.body, &#123; <span class="attr">attributes</span>: <span class="literal">true</span> &#125;); </span><br><span class="line"><span class="built_in">document</span>.body.className = <span class="string">&#x27;foo&#x27;</span>; </span><br><span class="line"><span class="built_in">console</span>.log(<span class="string">&#x27;Changed body class&#x27;</span>); </span><br><span class="line"><span class="comment">// Changed body class </span></span><br><span class="line"><span class="comment">// DOM was mutated!</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 撤销观察</span></span><br><span class="line">observer.disconnect();</span><br></pre></td></tr></table></figure>

<p>还有一些其他的关于这个observe的，但好像基本没见哪里用过，就不记了</p>
<p>DOM 由一系列节点类型构成，主要包括以下几种：</p>
<ul>
<li>Node 是基准节点类型，是文档一个部分的抽象表示，所有其他类型都继承 Node。 </li>
<li>Document 类型表示整个文档，对应树形结构的根节点。在 JavaScript 中，document 对象是Document 的实例，拥有查询和获取节点的很多方法。</li>
<li>Element 节点表示文档中所有 HTML 或 XML 元素，可以用来操作它们的内容和属性。</li>
<li>其他节点类型分别表示文本内容、注释、文档类型、CDATA 区块和文档片段。</li>
</ul>
<p><strong>自定义数据属性</strong></p>
<p>给元素指定非标准的属性，但要使用前缀 <strong>data-</strong> 以便告诉浏览器</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&lt;div id=<span class="string">&quot;myDiv&quot;</span> data-appId=<span class="string">&quot;12345&quot;</span> data-myname=<span class="string">&quot;Nicholas&quot;</span>&gt;&lt;/div&gt;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 示例</span></span><br><span class="line"><span class="keyword">let</span> div = <span class="built_in">document</span>.getElementById(<span class="string">&quot;myDiv&quot;</span>); </span><br><span class="line"><span class="comment">// 取得自定义数据属性的值</span></span><br><span class="line"><span class="keyword">let</span> appId = div.dataset.appId; </span><br><span class="line"><span class="keyword">let</span> myName = div.dataset.myname; </span><br><span class="line"><span class="comment">// 设置自定义数据属性的值</span></span><br><span class="line">div.dataset.appId = <span class="number">23456</span>; </span><br><span class="line">div.dataset.myname = <span class="string">&quot;Michael&quot;</span>; </span><br><span class="line"><span class="comment">// 有&quot;myname&quot;吗？</span></span><br><span class="line"><span class="keyword">if</span> (div.dataset.myname)&#123; </span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`Hello, <span class="subst">$&#123;div.dataset.myname&#125;</span>`</span>); </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>定义了自定义数据属性后，可以通过元素的 dataset 属性来访问</p>
<p>有一点需要说一下，在css里面似乎也跟这个值进行一些操作</p>
<h5 id="css自定义属性"><a href="#css自定义属性" class="headerlink" title="css自定义属性"></a><a target="_blank" rel="noopener" href="https://www.cnblogs.com/cangqinglang/p/11384703.html">css自定义属性</a></h5><p><code>--*</code>来声明变量名，<code>var(--*)</code>来使用</p>
<h4 id="元素尺寸"><a href="#元素尺寸" class="headerlink" title="元素尺寸"></a>元素尺寸</h4><h5 id="偏移尺寸"><a href="#偏移尺寸" class="headerlink" title="偏移尺寸"></a>偏移尺寸</h5><img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20210126183341271.png" alt="image-20210126183341271" style="zoom:80%;" />

<h5 id="客户端尺寸"><a href="#客户端尺寸" class="headerlink" title="客户端尺寸"></a>客户端尺寸</h5><img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20210126183438341.png" alt="image-20210126183438341" style="zoom:80%;" />

<p>除此之外还有一个 <strong>滚动尺寸</strong></p>
<img src="https://gitee.com/cheng_song/picgo-img/raw/master/img/image-20210126185456551.png" alt="image-20210126185456551" style="zoom:80%;" />

<h4 id="事件"><a href="#事件" class="headerlink" title="事件"></a>事件</h4><p>这一部分都是很原生的事件程序，可能vue的底层是基于这些来实现的，但我不会太过于记录</p>
<p><strong>冒泡</strong></p>
<p>事件被定义为从最具体的元素（文档树中最深的节点）开始触发，然后向上传播至没有那么具体的元素</p>
<p>DOM2 Events 规范规定事件流分为 3 个阶段：<strong>事件捕获、到达目标和事件冒泡</strong>。事件捕获最先发生，为提前拦截事件提供了可能。然后，实际的目标元素接收到事件。最后一个阶段是冒泡，最迟要在这个阶段响应事件</p>
<p>还有一些事件处理程序 如：click mouse这些    <strong>addEventListener()    removeEventListener()</strong> </p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">&lt;input type=<span class="string">&quot;button&quot;</span> value=<span class="string">&quot;Click Me&quot;</span> onclick=<span class="string">&quot;console.log(event.type)&quot;</span>&gt;</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> btn = <span class="built_in">document</span>.getElementById(<span class="string">&quot;myBtn&quot;</span>); </span><br><span class="line">btn.onclick = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>) </span>&#123; </span><br><span class="line"> <span class="built_in">console</span>.log(event.type); <span class="comment">// &quot;click&quot; </span></span><br><span class="line">&#125;; </span><br><span class="line">btn.addEventListener(<span class="string">&quot;click&quot;</span>, <span class="function">(<span class="params">event</span>) =&gt;</span> &#123; </span><br><span class="line"> <span class="built_in">console</span>.log(event.type); <span class="comment">// &quot;click&quot; </span></span><br><span class="line">&#125;, <span class="literal">false</span>);</span><br></pre></td></tr></table></figure>

<img src="C:\Users\admin\AppData\Roaming\Typora\typora-user-images\image-20210126215301158.png" alt="image-20210126215301158" style="zoom:80%;" />

<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 取得鼠标事件的客户端位置</span></span><br><span class="line"><span class="keyword">let</span> div = <span class="built_in">document</span>.getElementById(<span class="string">&quot;myDiv&quot;</span>); </span><br><span class="line">div.addEventListener(<span class="string">&quot;click&quot;</span>, <span class="function">(<span class="params">event</span>) =&gt;</span> &#123; </span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`Client coordinates: <span class="subst">$&#123;event.clientX&#125;</span>, <span class="subst">$&#123;event.clientY&#125;</span>`</span>); </span><br><span class="line">&#125;);</span><br><span class="line"><span class="comment">// 取得鼠标事件的页面位置</span></span><br><span class="line"><span class="keyword">let</span> div = <span class="built_in">document</span>.getElementById(<span class="string">&quot;myDiv&quot;</span>); </span><br><span class="line">div.addEventListener(<span class="string">&quot;click&quot;</span>, <span class="function">(<span class="params">event</span>) =&gt;</span> &#123; </span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">`Page coordinates: <span class="subst">$&#123;event.pageX&#125;</span>, <span class="subst">$&#123;event.pageY&#125;</span>`</span>); </span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure>

<p>最好限制一个页面中事件处理程序的数量，因为它们会占用过多内存，导致页面响应缓慢</p>
<h4 id="canvas"><a href="#canvas" class="headerlink" title="canvas"></a>canvas</h4><p>之前简单看了一下感觉讲了一些基本的东西，没有太深入，这里就不记了</p>
<p>如果需要的话，看一下教学视频感觉也比这个要好</p>
<p>后面还有一些关于<strong>表单脚本</strong>（里面关于富文本编辑器的那一节会简单写下），除了这个还有一些其他的感觉没他大用的，所以后面会比前面更精简的记录一些核心知识点</p>
<h5 id="富文本编辑"><a href="#富文本编辑" class="headerlink" title="富文本编辑"></a>富文本编辑</h5><p>这里没有记录js如何引入富文本编辑器，只是说了一下编辑器的一些属性，就挑着一些记一下吧</p>
<p><strong>contenteditable</strong> 让任何一个元素都可编辑</p>
<p>好吧，都是一堆关于编辑器的属性，没啥好记的</p>
<h4 id="重要的API"><a href="#重要的API" class="headerlink" title="重要的API"></a>重要的API</h4><p>这里就记一些感觉重要的api</p>
<p><strong>Atomics</strong> 原子性操作，主要是对缓冲区里面的值进行操作，有 add or and xor这些读写 与 异或等操作</p>
<p><strong>postMessage()</strong> 跨上下文交流消息，主要是对iframe这种两个页面之间进行交流</p>
<p><strong>文本编码</strong></p>
<p>TextEncoder、TextEncoderStream、TextDecoder 和 TextDecoderStream</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">const</span> textEncoder = <span class="keyword">new</span> TextEncoder(); </span><br><span class="line"><span class="keyword">const</span> decodedText = <span class="string">&#x27;foo&#x27;</span>; </span><br><span class="line"><span class="keyword">const</span> encodedText = textEncoder.encode(decodedText);</span><br><span class="line"><span class="comment">// f 的 UTF-8 编码是 0x66（即十进制 102）</span></span><br><span class="line"><span class="comment">// o 的 UTF-8 编码是 0x6F（即二进制 111）</span></span><br><span class="line"><span class="built_in">console</span>.log(encodedText); <span class="comment">// Uint8Array(3) [102, 111, 111]</span></span><br><span class="line"><span class="keyword">const</span> decodedText1 = textDecoder.decode(encodedText);</span><br><span class="line"><span class="built_in">console</span>.log(decodedText1); <span class="comment">// foo</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 特殊字符可能会占多个索引</span></span><br><span class="line"><span class="keyword">const</span> decodedText1 = <span class="string">&#x27;☺&#x27;</span>; </span><br><span class="line"><span class="keyword">const</span> encodedText1 = textEncoder.encode(decodedText); </span><br><span class="line"><span class="comment">// ☺的 UTF-8 编码是 0xF0 0x9F 0x98 0x8A（即十进制 240、159、152、138）</span></span><br><span class="line"><span class="built_in">console</span>.log(encodedText1); <span class="comment">// Uint8Array(4) [240, 159, 152, 138]</span></span><br></pre></td></tr></table></figure>

<h5 id="file类型"><a href="#file类型" class="headerlink" title="file类型"></a>file类型</h5><p>每个 File 对象都有一些只读属性：</p>
<ul>
<li>name：本地系统中的文件名。</li>
<li>size：以字节计的文件大小。</li>
<li>type：包含文件 MIME 类型的字符串。</li>
<li>lastModifiedDate：表示文件最后修改时间的字符串。这个属性只有 Chome 实现了。</li>
</ul>
<hr>
<p>File API 还提供了 FileReader 类型，让我们可以实际从文件中读取数据</p>
<p>FileReader 类型提供了几个读取文件数据的方法。</p>
<ul>
<li>readAsText(file, encoding)：从文件中读取纯文本内容并保存在 result 属性中。第二个参数表示编码，是可选的。</li>
<li>readAsDataURL(file)：读取文件并将内容的数据 URI 保存在 result 属性中。</li>
<li>readAsBinaryString(file)：读取文件并将每个字符的二进制数据保存在 result 属性中。</li>
<li>readAsArrayBuffer(file)：读取文件并将文件内容以 ArrayBuffer 形式保存在 result 属性</li>
</ul>
<p>每个 FileReader 会发布几个事件，其中 3 个最有用的事件是progress、error 和 load，分别表示还有更多数据、发生了错误和读取完成。</p>
<hr>
<p>还有一个Blob对象，表示一个二进制大对象，是 JavaScript 对不可修改二进制数据的封装类型</p>
<p>还有一个对象URL（Blob URL），是指引用存储在 File 或 Blob 中数据的 URL。对象 URL 的优点是不用把文件内容读取到 JavaScript 也可以使用文件。</p>
<p>要创建对象 URL，可以使用 window.URL.createObjectURL()方法并传入 File 或 Blob 对象。这个函数返回的值是一个指向内存中地址的字符串。因为这个字符串是 URL，所以可以在 DOM 中直接使用，以前好像见过有一个下载文件的代码就好像使用了这个</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 使用blob对象存储下载文件</span></span><br><span class="line"><span class="function"><span class="title">downUrl</span>(<span class="params">url</span>)</span> &#123;</span><br><span class="line">   <span class="comment">// window.open(_this.detail.imgUrl)</span></span><br><span class="line">   <span class="keyword">let</span> xmlhttp = <span class="keyword">new</span> XMLHttpRequest();</span><br><span class="line">   xmlhttp.open(<span class="string">&quot;GET&quot;</span>, url, <span class="literal">true</span>);</span><br><span class="line">   <span class="comment">// 注意这里</span></span><br><span class="line">   xmlhttp.responseType = <span class="string">&quot;blob&quot;</span>;</span><br><span class="line">   <span class="comment">// 在请求完成的时候</span></span><br><span class="line">   xmlhttp.onload = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">     <span class="keyword">if</span> (<span class="built_in">this</span>.status == <span class="number">200</span>) &#123;</span><br><span class="line">       <span class="keyword">const</span> blob = <span class="built_in">this</span>.response;</span><br><span class="line">       <span class="keyword">const</span> link = <span class="built_in">document</span>.createElement(<span class="string">&#x27;a&#x27;</span>);</span><br><span class="line">       <span class="comment">// 还有这里</span></span><br><span class="line">       link.href = <span class="built_in">window</span>.URL.createObjectURL(blob);</span><br><span class="line">       link.download = url.substring(url.lastIndexOf(<span class="string">&quot;/&quot;</span>) + <span class="number">1</span>, url.length);</span><br><span class="line">       <span class="built_in">document</span>.body.appendChild(link);</span><br><span class="line">       <span class="keyword">const</span> evt = <span class="built_in">document</span>.createEvent(<span class="string">&quot;MouseEvents&quot;</span>);</span><br><span class="line">       evt.initEvent(<span class="string">&quot;click&quot;</span>, <span class="literal">false</span>, <span class="literal">false</span>);</span><br><span class="line">       link.dispatchEvent(evt);</span><br><span class="line">       <span class="built_in">window</span>.URL.revokeObjectURL(link.href)</span><br><span class="line">       <span class="built_in">document</span>.body.removeChild(link);</span><br><span class="line">     &#125;</span><br><span class="line">     ;</span><br><span class="line">   &#125;</span><br><span class="line">   xmlhttp.send();</span><br><span class="line"> &#125;</span><br></pre></td></tr></table></figure>

<p>还有一个读取拖放文件的功能，结合拖放的元素api和file的api进行实现</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">let</span> droptarget = <span class="built_in">document</span>.getElementById(<span class="string">&quot;droptarget&quot;</span>); </span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">handleEvent</span>(<span class="params">event</span>) </span>&#123; </span><br><span class="line"> <span class="keyword">let</span> info = <span class="string">&quot;&quot;</span>, </span><br><span class="line"> output = <span class="built_in">document</span>.getElementById(<span class="string">&quot;output&quot;</span>), </span><br><span class="line"> files, i, len; </span><br><span class="line"> event.preventDefault(); </span><br><span class="line"> <span class="keyword">if</span> (event.type == <span class="string">&quot;drop&quot;</span>) &#123; </span><br><span class="line">     <span class="comment">// 在这里读取文件</span></span><br><span class="line">     files = event.dataTransfer.files; </span><br><span class="line">     i = <span class="number">0</span>; </span><br><span class="line">     len = files.length; </span><br><span class="line">     <span class="keyword">while</span> (i &lt; len) &#123; </span><br><span class="line">         info += <span class="string">`<span class="subst">$&#123;files[i].name&#125;</span> (<span class="subst">$&#123;files[i].type&#125;</span>, <span class="subst">$&#123;files[i].size&#125;</span> bytes)&lt;br&gt;`</span>; </span><br><span class="line">         i++; </span><br><span class="line">     &#125; </span><br><span class="line">     output.innerHTML = info; </span><br><span class="line"> &#125; </span><br><span class="line">&#125; </span><br><span class="line">droptarget.addEventListener(<span class="string">&quot;dragenter&quot;</span>, handleEvent); </span><br><span class="line">droptarget.addEventListener(<span class="string">&quot;dragover&quot;</span>, handleEvent); </span><br><span class="line">droptarget.addEventListener(<span class="string">&quot;drop&quot;</span>, handleEvent);</span><br></pre></td></tr></table></figure>

<hr>
<p><strong>媒体元素</strong></p>
<p>比如 <video> <audio> 这两个标签里面就有一些属性和事件需要注意</p>
<h5 id="Page-Visibility-API"><a href="#Page-Visibility-API" class="headerlink" title="Page Visibility API"></a><strong>Page Visibility API</strong></h5><p>这个api表示下面 4 种状态之一：</p>
<ul>
<li>页面在后台标签页或浏览器中最小化了。</li>
<li>页面在前台标签页中。</li>
<li>实际页面隐藏了，但对页面的预览是可见的（例如在 Windows 7 上，用户鼠标移到任务栏图标上会显示网页预览）。</li>
<li>页面在屏外预渲染。</li>
</ul>
<p>可根据这个api判断用户是否需要显示这个页面，由此能知道是否应该暂停轮询服务器、更新动画这些</p>
<h5 id="计时api"><a href="#计时api" class="headerlink" title="计时api"></a>计时api</h5><figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">// 毫秒精度</span><br><span class="line">const t0 = Date.now();</span><br><span class="line">// 微妙精度</span><br><span class="line">const t1 = window.performance.now()</span><br></pre></td></tr></table></figure>

<p>还有一些关于测量页面性能、加载时间这些的api就不记了</p>
<p>后面还有关于随机数和加密的api</p>
<p>浏览器调试的 debugger （在代码里面写上） 之后就能在浏览器控制台一步步执行调试</p>
<hr>
<p>后面还有一些关于网络请求的api 如<strong>xhr</strong>（上面有其使用方式，其忽悠同源策略，所以就有了一些cores的跨域手段）    <strong>fetch</strong>这些，感觉现在基本没有用到这些，就不进行记录了</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">fetch(<span class="string">&#x27;bar.txt&#x27;</span>) </span><br><span class="line"> .then(<span class="function">(<span class="params">response</span>) =&gt;</span> &#123; </span><br><span class="line"> <span class="built_in">console</span>.log(response); </span><br><span class="line"> &#125;); </span><br><span class="line"><span class="comment">// Response &#123; type: &quot;basic&quot;, url: ... &#125;</span></span><br></pre></td></tr></table></figure>

<hr>
<p><strong>web socket</strong></p>
<p>通过一个长时连接实现与服务器全双工、双向的通信</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 必须给 WebSocket 构造函数传入一个绝对 URL。同源策略不适用于 Web Socket，因此可以打开到任意站点的连接</span></span><br><span class="line"><span class="keyword">let</span> socket = <span class="keyword">new</span> WebSocket(<span class="string">&quot;ws://www.example.com/server.php&quot;</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> stringData = <span class="string">&quot;Hello world!&quot;</span>; </span><br><span class="line"><span class="keyword">let</span> arrayBufferData = <span class="built_in">Uint8Array</span>.from([<span class="string">&#x27;f&#x27;</span>, <span class="string">&#x27;o&#x27;</span>, <span class="string">&#x27;o&#x27;</span>]); </span><br><span class="line"><span class="keyword">let</span> blobData = <span class="keyword">new</span> Blob([<span class="string">&#x27;f&#x27;</span>, <span class="string">&#x27;o&#x27;</span>, <span class="string">&#x27;o&#x27;</span>]); </span><br><span class="line"></span><br><span class="line">socket.send(stringData); </span><br><span class="line">socket.send(arrayBufferData.buffer); </span><br><span class="line">socket.send(blobData);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 服务端向客户端发送信息时进行接收</span></span><br><span class="line">socket.onmessage = <span class="function"><span class="keyword">function</span>(<span class="params">event</span>) </span>&#123; </span><br><span class="line"> <span class="keyword">let</span> data = event.data; </span><br><span class="line"> <span class="comment">// 对数据执行某些操作</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">socket.close();</span><br></pre></td></tr></table></figure>

<p>还有一些关于连接状态之类的api就不记了</p>
<hr>
<p>下面是一些关于客户端存储的东西</p>
<p>**cookie（主要是跟服务器进行沟通时进行交换）    **    <strong>storage（持久化存储大量数据 存储上限由浏览器决定 有两种 session/local）</strong>    </p>
<p>还有一个<strong>indexDB</strong>，一个类似mysql的数据库，使用对象存储</p>
<hr>
<p>下一个是 <strong><a target="_blank" rel="noopener" href="http://www.ruanyifeng.com/blog/2018/07/web-worker.html">web worker</a></strong> 用来创建一个子线程进行一些操作并与主线程进行沟通</p>
<p>主要是用来执行一些耗费时间的任务，如网络请求、文件输入输出这些会导致主线程卡顿的任务</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line">emptyWorker.js</span><br><span class="line"><span class="comment">// 空的 JS 工作者线程文件</span></span><br><span class="line"><span class="built_in">this</span>.addEventListener(<span class="string">&#x27;message&#x27;</span>, <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">this</span>.postMessage(<span class="string">&#x27;You said: &#x27;</span> + e.data);</span><br><span class="line">&#125;, <span class="literal">false</span>);</span><br><span class="line"></span><br><span class="line">main.js</span><br><span class="line"><span class="built_in">console</span>.log(location.href); <span class="comment">// &quot;https://example.com/&quot; </span></span><br><span class="line"><span class="keyword">const</span> worker = <span class="keyword">new</span> Worker(location.href + <span class="string">&#x27;emptyWorker.js&#x27;</span>);</span><br><span class="line"><span class="built_in">console</span>.log(worker); <span class="comment">// Worker &#123;&#125;</span></span><br><span class="line">worker.postMessage(<span class="string">&#x27;Hello World&#x27;</span>);</span><br><span class="line">worker.onmessage = <span class="function"><span class="keyword">function</span> (<span class="params">event</span>) </span>&#123;</span><br><span class="line">  <span class="built_in">console</span>.log(<span class="string">&#x27;Received message &#x27;</span> + event.data);</span><br><span class="line">  doSomething();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>后面还有一些关于worker安全性之类的东西</p>
<h4 id="最后"><a href="#最后" class="headerlink" title="最后"></a>最后</h4><p>这就是一个简单的看了一遍书，对书中的重难点都没有怎么深入核心，可能原因是现在还没有见过这些东西，或者说现在我是用的都是别人封装好的框架、轮子，只是使用，对其底层原理并没有深入，所以就先这样吧。以后如果有需要再对这些底层的东西进行深入了解</p>
</div></article><div class="post-copyright"><div class="post-copyright__author"><span class="post-copyright-meta">文章作者: </span><span class="post-copyright-info"><a href="mailto:undefined">晟松</a></span></div><div class="post-copyright__type"><span class="post-copyright-meta">文章链接: </span><span class="post-copyright-info"><a href="https://chengsong.info/2021/01/21/js高级程序指南第四版-学习记录/">https://chengsong.info/2021/01/21/js高级程序指南第四版-学习记录/</a></span></div><div class="post-copyright__notice"><span class="post-copyright-meta">版权声明: </span><span class="post-copyright-info">本博客所有文章除特别声明外，均采用 <a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/">CC BY-NC-SA 4.0</a> 许可协议。转载请注明来自 <a href="https://chengsong.info">晟松</a>！</span></div></div><div class="post-meta__tag-list"><a class="post-meta__tags" href="/tags/js/">js</a></div><nav id="pagination"><div class="prev-post pull-left"><a href="/2021/01/31/Nuxtjs%E5%88%9D%E5%AD%A6%E4%B9%A0/"><i class="fa fa-chevron-left">  </i><span>Nuxtjs初学习</span></a></div><div class="next-post pull-right"><a href="/2021/01/10/scss%20less%E7%9A%84%E7%AE%80%E5%8D%95%E5%AD%A6%E4%B9%A0/"><span>scss less的简单学习</span><i class="fa fa-chevron-right"></i></a></div></nav></div></div><footer class="footer-bg" style="background-image: url(/img/blog-bg.jpg)"><div class="layout" id="footer"><div class="copyright">&copy;2020 - 2023 By 晟松</div><div class="framework-info"><span>驱动 - </span><a target="_blank" rel="noopener" href="http://hexo.io"><span>Hexo</span></a><span class="footer-separator">|</span><span>主题 - </span><a target="_blank" rel="noopener" href="https://github.com/Molunerfinn/hexo-theme-melody"><span>Melody</span></a></div><div class="icp"><a target="_blank" rel="noopener" href="http://www.beian.miit.gov.cn/"><span>湘ICP备2020021729号</span></a></div><div class="busuanzi"><script async src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script><span id="busuanzi_container_page_pv"><i class="fa fa-file"></i><span id="busuanzi_value_page_pv"></span><span></span></span></div></div></footer><i class="fa fa-arrow-up" id="go-up" aria-hidden="true"></i><script src="https://cdn.jsdelivr.net/npm/animejs@latest/anime.min.js"></script><script src="https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js"></script><script src="https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js"></script><script src="https://cdn.jsdelivr.net/npm/velocity-animate@latest/velocity.min.js"></script><script src="https://cdn.jsdelivr.net/npm/velocity-ui-pack@latest/velocity.ui.min.js"></script><script src="/js/utils.js?version=1.9.0"></script><script src="/js/fancybox.js?version=1.9.0"></script><script src="/js/sidebar.js?version=1.9.0"></script><script src="/js/copy.js?version=1.9.0"></script><script src="/js/fireworks.js?version=1.9.0"></script><script src="/js/transition.js?version=1.9.0"></script><script src="/js/scroll.js?version=1.9.0"></script><script src="/js/head.js?version=1.9.0"></script><script src="/js/search/local-search.js"></script><script>if(/Android|webOS|iPhone|iPod|iPad|BlackBerry/i.test(navigator.userAgent)) {
  $('#nav').addClass('is-mobile')
  $('footer').addClass('is-mobile')
  $('#top-container').addClass('is-mobile')
}</script><div class="search-dialog" id="local-search"><div class="search-dialog__title" id="local-search-title">本地搜索</div><div id="local-input-panel"><div id="local-search-input"><div class="local-search-box"><input class="local-search-box--input" placeholder="搜索文章"></div></div></div><hr><div id="local-search-results"><div id="local-hits"></div><div id="local-stats"><div class="local-search-stats__hr" id="hr"><span>由</span> <a target="_blank" rel="noopener" href="https://github.com/wzpan/hexo-generator-search" style="color:#49B1F5;">hexo-generator-search</a>
 <span>提供支持</span></div></div></div><span class="search-close-button"><i class="fa fa-times"></i></span></div><div class="search-mask"></div></body></html>